Snap for 7803083 from f90e90550b610f6e8fe5532a43618756e8c1d409 to mainline-tzdata2-release
Change-Id: I7facfdcc864191c2bc307a4b1f5d547c4931aa5e
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2732435
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+# Generated build files
+gen/com/android/networkstack/**
+
+# IntelliJ project files
+**/.idea
+**/*.iml
+**/*.ipr
diff --git a/Android.bp b/Android.bp
index 802ca42..0f577a4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,12 +22,12 @@
// / \
// +NetworkStackApiStableShims --> / \ <-- +NetworkStackApiCurrentShims
// +NetworkStackReleaseApiLevel / \ +NetworkStackDevApiLevel
-// +jarjar apistub.api[latest].* / \ +module src/
-// to apistub.* / \
+// +jarjar apishim.api[latest].* / \
+// to apishim.* / \
// / \
-// NetworkStackApiStableDependencies \
+// / \
// / \ android libs w/ all code
-// +module src/ --> / \ (also used in unit tests)
+// / <- +module src/ -> \ (also used in unit tests)
// / \ |
// NetworkStackApiStableLib NetworkStackApiCurrentLib <--*
// | |
@@ -41,6 +41,10 @@
// TestNetworkStack
// Common defaults to define SDK level
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_defaults {
name: "NetworkStackDevApiLevel",
min_sdk_version: "29",
@@ -49,32 +53,153 @@
java_defaults {
name: "NetworkStackReleaseApiLevel",
- sdk_version: "system_30",
+ sdk_version: "module_31",
min_sdk_version: "29",
- target_sdk_version: "30",
+ target_sdk_version: "31",
+ libs: [
+ "framework-connectivity",
+ "framework-statsd",
+ "framework-wifi",
+ ]
}
-// Filegroups for the API shims
-filegroup {
- name: "NetworkStackApiCurrentShims",
+// Libraries for the API shims
+java_defaults {
+ name: "NetworkStackShimsDefaults",
+ libs: [
+ "androidx.annotation_annotation",
+ "networkstack-client",
+ ],
+ static_libs : [
+ "modules-utils-build_system"
+ ],
+ apex_available: [
+ "com.android.tethering",
+ "//apex_available:platform", // For InProcessNetworkStack and InProcessTethering
+ ],
+ min_sdk_version: "29",
+}
+
+// Common shim code. This includes the shim interface definitions themselves, and things like
+// ShimUtils and UnsupportedApiLevelException. Compiles against system_current because ShimUtils
+// needs access to all Build.VERSION_CODES.*, which by definition are only in the newest SDK.
+// TODO: consider moving ShimUtils into a library (or removing it in favour of SdkLevel) and compile
+// this target against the lowest-supported SDK (currently 29).
+java_library {
+ name: "NetworkStackShimsCommon",
+ defaults: ["NetworkStackShimsDefaults"],
+ srcs: ["apishim/common/**/*.java"],
+ sdk_version: "system_current",
+ visibility: ["//visibility:private"],
+}
+
+// Each level of the shims (29, 30, ...) is its own java_library compiled against the corresponding
+// system_X SDK. this ensures that each shim can only use SDK classes that exist in its SDK level.
+java_library {
+ name: "NetworkStackApi29Shims",
+ defaults: ["NetworkStackShimsDefaults"],
+ srcs: ["apishim/29/**/*.java"],
+ libs: [
+ "NetworkStackShimsCommon",
+ ],
+ sdk_version: "system_29",
+ visibility: ["//visibility:private"],
+}
+
+java_library {
+ name: "NetworkStackApi30Shims",
+ defaults: ["NetworkStackShimsDefaults"],
srcs: [
- "apishim/common/**/*.java",
- "apishim/29/**/*.java",
"apishim/30/**/*.java",
+ ],
+ libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ ],
+ sdk_version: "system_30",
+ visibility: ["//visibility:private"],
+ lint: {
+ baseline_filename: "lint-baseline-api-30-shims.xml",
+ },
+}
+
+// Shims for APIs being added to the current development version of Android. These APIs are not
+// stable and have no defined version number. These could be called 10000, but they use the next
+// integer so if the next SDK release happens to use that integer, we don't need to rename them.
+java_library {
+ name: "NetworkStackApi31Shims",
+ defaults: ["NetworkStackShimsDefaults"],
+ srcs: [
"apishim/31/**/*.java",
- ":networkstack-module-utils-srcs",
+ ],
+ libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ "NetworkStackApi30Shims",
+ "framework-connectivity",
+ ],
+ sdk_version: "module_31",
+ visibility: ["//visibility:private"],
+}
+
+
+// Shims for APIs being added to the current development version of Android. These APIs are not
+// stable and have no defined version number. These could be called 10000, but they use the next
+// integer so if the next SDK release happens to use that integer, we don't need to rename them.
+java_library {
+ name: "NetworkStackApi32Shims",
+ defaults: ["NetworkStackShimsDefaults"],
+ srcs: [
+ "apishim/32/**/*.java",
+ ],
+ libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ "NetworkStackApi30Shims",
+ "NetworkStackApi31Shims",
+ "framework-connectivity",
+ ],
+ sdk_version: "module_current",
+ visibility: ["//visibility:private"],
+}
+
+// API current uses the API current shims directly.
+// The current (in-progress) shims are in the com.android.networkstack.apishim package and are
+// called directly by the networkstack code.
+java_library {
+ name: "NetworkStackApiCurrentShims",
+ defaults: ["NetworkStackShimsDefaults"],
+ static_libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ "NetworkStackApi30Shims",
+ "NetworkStackApi31Shims",
+ "NetworkStackApi32Shims",
+ ],
+ sdk_version: "module_current",
+ visibility: [
+ "//packages/modules/Connectivity/Tethering",
+ "//packages/modules/Connectivity/tests/cts/net",
],
}
-// API stable shims only include the compat package, but it is jarjared to replace the non-compat
-// package
-filegroup {
+// API stable uses jarjar to rename the latest stable apishim package from
+// com.android.networkstack.apishim.apiXX to com.android.networkstack.apishim, which is called by
+// the networkstack code.
+java_library {
name: "NetworkStackApiStableShims",
- srcs: [
- "apishim/common/**/*.java",
- "apishim/29/**/*.java",
- "apishim/30/**/*.java",
- ":networkstack-module-utils-srcs",
+ defaults: ["NetworkStackShimsDefaults"],
+ static_libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ "NetworkStackApi30Shims",
+ "NetworkStackApi31Shims",
+ ],
+ jarjar_rules: "apishim/jarjar-rules-compat.txt",
+ sdk_version: "module_31",
+ visibility: [
+ "//packages/modules/Connectivity/Tethering",
+ "//packages/modules/Connectivity/tests/cts/net",
],
}
@@ -84,12 +209,13 @@
name: "NetworkStackAndroidLibraryDefaults",
srcs: [
":framework-networkstack-shared-srcs",
+ ":networkstack-module-utils-srcs",
],
libs: ["unsupportedappusage"],
static_libs: [
"androidx.annotation_annotation",
- "netd_aidl_interface-java",
- "netlink-client",
+ "modules-utils-build_system",
+ "netd_aidl_interface-lateststable-java",
"networkstack-client",
"net-utils-framework-common",
// See note on statsprotos when adding/updating proto build rules
@@ -97,47 +223,54 @@
"statsprotos",
"captiveportal-lib",
"net-utils-device-common",
+ "net-utils-device-common-netlink",
],
plugins: ["java_api_finder"],
}
-// The versions of the android library containing network stack code compiled for each SDK variant
-// API current uses the sources of the API current shims directly.
-// This allows API current code to be treated identically to code in src/ (it will be moved
-// there eventually), and to use the compat shim as fallback on older devices.
+// The versions of the android library containing network stack code compiled for each SDK variant.
android_library {
name: "NetworkStackApiCurrentLib",
defaults: ["NetworkStackDevApiLevel", "NetworkStackAndroidLibraryDefaults"],
srcs: [
- ":NetworkStackApiCurrentShims",
"src/**/*.java",
":statslog-networkstack-java-gen-current"
],
+ static_libs: ["NetworkStackApiCurrentShims"],
manifest: "AndroidManifestBase.xml",
- enabled: false, // Disabled in mainline-prod
-}
-
-// For API stable, first build the dependencies using jarjar compat rules, then build the sources
-// linking with the dependencies.
-java_library {
- name: "NetworkStackApiStableDependencies",
- defaults: ["NetworkStackReleaseApiLevel", "NetworkStackAndroidLibraryDefaults"],
- srcs: [":NetworkStackApiStableShims"],
- jarjar_rules: "apishim/jarjar-rules-compat.txt",
+ visibility: [
+ "//frameworks/base/tests/net/integration",
+ "//packages/modules/Connectivity/Tethering/tests/integration",
+ "//packages/modules/Connectivity/tests/cts/net",
+ "//packages/modules/NetworkStack/tests/unit",
+ "//packages/modules/NetworkStack/tests/integration",
+ ],
+ lint: {
+ baseline_filename: "lint-baseline-current-lib.xml",
+ },
}
android_library {
name: "NetworkStackApiStableLib",
- defaults: ["NetworkStackReleaseApiLevel"],
+ defaults: ["NetworkStackReleaseApiLevel", "NetworkStackAndroidLibraryDefaults"],
srcs: [
"src/**/*.java",
":statslog-networkstack-java-gen-stable",
],
- // API stable uses a jarjared version of the shims
- static_libs: [
- "NetworkStackApiStableDependencies",
- ],
+ static_libs: ["NetworkStackApiStableShims"],
manifest: "AndroidManifestBase.xml",
+ visibility: [
+ "//frameworks/base/packages/Connectivity/tests/integration",
+ "//frameworks/base/tests/net/integration",
+ "//packages/modules/Connectivity/Tethering/tests/integration",
+ "//packages/modules/Connectivity/tests/cts/net",
+ "//packages/modules/Connectivity/tests/integration",
+ "//packages/modules/NetworkStack/tests/unit",
+ "//packages/modules/NetworkStack/tests/integration",
+ ],
+ lint: {
+ baseline_filename: "lint-baseline-stable-lib.xml",
+ },
}
filegroup {
@@ -146,7 +279,7 @@
visibility: [
"//packages/modules/NetworkStack/tests/unit",
"//packages/modules/NetworkStack/tests/integration",
- "//frameworks/base/packages/Tethering/tests/integration",
+ "//packages/modules/Connectivity/tests:__subpackages__",
"//packages/modules/Connectivity/Tethering/tests/integration",
]
}
@@ -180,8 +313,10 @@
// The permission configuration *must* be included to ensure security of the device
// The InProcessNetworkStack goes together with the PlatformCaptivePortalLogin, which replaces
// the default CaptivePortalLogin.
- required: ["PlatformNetworkPermissionConfig", "PlatformCaptivePortalLogin"],
- enabled: false, // Disabled in mainline-prod
+ required: [
+ "PlatformNetworkPermissionConfig",
+ "PlatformCaptivePortalLogin",
+ ],
}
// Pre-merge the AndroidManifest for NetworkStackNext, so that its manifest can be merged on top
@@ -189,8 +324,7 @@
name: "NetworkStackNextManifestBase",
defaults: ["NetworkStackAppDefaults", "NetworkStackDevApiLevel"],
static_libs: ["NetworkStackApiCurrentLib"],
- manifest: "AndroidManifest.xml",
- enabled: false, // Disabled in mainline-prod
+ manifest: "AndroidManifest.xml"
}
// NetworkStack build targeting the current API release, for testing on in-development SDK
@@ -201,8 +335,10 @@
certificate: "networkstack",
manifest: "AndroidManifest_Next.xml",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
- enabled: false, // Disabled in mainline-prod
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
+ ],
}
// Updatable network stack for finalized API
@@ -213,21 +349,11 @@
certificate: "networkstack",
manifest: "AndroidManifest.xml",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
- updatable: true,
-}
-
-// Android library to derive test APKs for integration tests
-android_library {
- name: "TestNetworkStackLib",
- defaults: ["NetworkStackAppDefaults", "NetworkStackReleaseApiLevel"],
- static_libs: ["NetworkStackApiStableLib"],
- manifest: "AndroidManifestBase.xml",
- visibility: [
- "//frameworks/base/tests/net/integration",
- "//cts/tests/tests/net",
- "//packages/modules/Connectivity/tests/cts/net",
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
],
+ updatable: true,
}
cc_library_shared {
@@ -303,7 +429,10 @@
certificate: "networkstack",
manifest: ":NetworkStackTestAndroidManifest",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
+ ],
}
// When adding or modifying protos, the jarjar rules and possibly proguard rules need
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 55357a8..8750795 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,8 +19,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack"
- android:versionCode="309999900"
- android:versionName="r_aml_309999900"
+ android:versionCode="319999900"
+ android:versionName="s_aml_319999900"
+ coreApp="true"
>
<!-- Permissions must be defined here, and not in the base manifest, as the network stack
running in the system server process does not need any permission, and having privileged
diff --git a/AndroidManifest_InProcess.xml b/AndroidManifest_InProcess.xml
index 2cb146a..6c64d87 100644
--- a/AndroidManifest_InProcess.xml
+++ b/AndroidManifest_InProcess.xml
@@ -19,7 +19,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack.inprocess"
android:sharedUserId="android.uid.system"
- android:process="system">
+ android:process="system"
+ coreApp="true">
<application>
<service android:name="com.android.server.NetworkStackService"
android:process="system"
diff --git a/AndroidManifest_Next.xml b/AndroidManifest_Next.xml
index 02fcb64..244d465 100644
--- a/AndroidManifest_Next.xml
+++ b/AndroidManifest_Next.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack"
- android:versionCode="300000000"
- android:versionName="R-next">
+ android:versionCode="320000000"
+ android:versionName="T-next"
+ coreApp="true">
</manifest>
diff --git a/OWNERS b/OWNERS
index 0e1e65d..8cb7492 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,5 +2,7 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a2ed850..ed6a1a8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -5,11 +5,31 @@
},
{
"name": "NetworkStackNextTests"
+ },
+ {
+ "name": "NetworkStackIntegrationTests"
}
],
"postsubmit": [
{
"name": "NetworkStackHostTests"
+ }
+ ],
+ "auto-postsubmit": [
+ // Test tag for automotive targets. These are only running in postsubmit so as to harden the
+ // automotive targets to avoid introducing additional test flake and build time. The plan for
+ // presubmit testing for auto is to augment the existing tests to cover auto use cases as well.
+ // Additionally, this tag is used in targeted test suites to limit resource usage on the test
+ // infra during the hardening phase.
+ // TODO: this tag to be removed once the above is no longer an issue.
+ {
+ "name": "NetworkStackTests"
+ },
+ {
+ "name": "NetworkStackNextTests"
+ },
+ {
+ "name": "NetworkStackHostTests"
},
{
"name": "NetworkStackIntegrationTests"
@@ -23,6 +43,11 @@
"name": "NetworkStackTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]"
}
],
+ "mainline-postsubmit": [
+ {
+ "name": "NetworkStackIntegrationTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]"
+ }
+ ],
"imports": [
{
"path": "packages/modules/Connectivity"
diff --git a/apishim/29/com/android/networkstack/apishim/api29/CaptivePortalDataShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/CaptivePortalDataShimImpl.java
index 42216a9..8719e83 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/CaptivePortalDataShimImpl.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/CaptivePortalDataShimImpl.java
@@ -16,7 +16,7 @@
package com.android.networkstack.apishim.api29;
-import android.net.CaptivePortalData;
+import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -28,7 +28,7 @@
import org.json.JSONObject;
/**
- * Compatibility implementation of {@link CaptivePortalDataShim}.
+ * Compatibility implementation of {@link CaptivePortalData}.
*
* <p>Use {@link com.android.networkstack.apishim.CaptivePortalDataShimImpl} instead of this
* fallback implementation.
@@ -37,7 +37,7 @@
protected CaptivePortalDataShimImpl() {}
/**
- * Parse a {@link android.net.CaptivePortalData} from JSON.
+ * Parse a {@link android.net.CaptivePortalDataShim} from JSON.
*
* <p>Use
* {@link com.android.networkstack.apishim.CaptivePortalDataShimImpl#fromJson(JSONObject)}
@@ -51,24 +51,51 @@
}
@Override
- public String getVenueFriendlyName() {
+ public CharSequence getVenueFriendlyName() {
// Not supported in API level 29
return null;
}
+ @Override
+ public int getUserPortalUrlSource() {
+ // Not supported in API level 29
+ return ConstantsShim.CAPTIVE_PORTAL_DATA_SOURCE_OTHER;
+ }
+
@VisibleForTesting
public static boolean isSupported() {
return false;
}
/**
- * Generate a {@link CaptivePortalData} object with a friendly name set
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name set
*
* @param friendlyName The friendly name to set
* @return a {@link CaptivePortalData} object with a friendly name set
*/
- public CaptivePortalData withVenueFriendlyName(String friendlyName) {
+ @Override
+ public CaptivePortalDataShim withVenueFriendlyName(String friendlyName)
+ throws UnsupportedApiLevelException {
// Not supported in API level 29
- return null;
+ throw new UnsupportedApiLevelException("CaptivePortalData not supported on API 29");
+ }
+
+ /**
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name and Passpoint external
+ * URLs set
+ *
+ * @param friendlyName The friendly name to set
+ * @param venueInfoUrl Venue information URL
+ * @param termsAndConditionsUrl Terms and conditions URL
+ *
+ * @return a {@link CaptivePortalDataShim} object with friendly name, venue info URL and terms
+ * and conditions URL set
+ */
+ @Override
+ public CaptivePortalDataShim withPasspointInfo(@NonNull String friendlyName,
+ @NonNull Uri venueInfoUrl, @NonNull Uri termsAndConditionsUrl)
+ throws UnsupportedApiLevelException {
+ // Not supported in API level 29
+ throw new UnsupportedApiLevelException("CaptivePortalData not supported on API 29");
}
}
diff --git a/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java
new file mode 100644
index 0000000..07327be
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api29;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+/**
+ * Implementation of {@link ConnectivityManagerShim} for API 29.
+ */
+public class ConnectivityManagerShimImpl implements ConnectivityManagerShim {
+ protected final ConnectivityManager mCm;
+ protected ConnectivityManagerShimImpl(Context context) {
+ mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ /**
+ * Get a new instance of {@link ConnectivityManagerShim}.
+ */
+ public static ConnectivityManagerShim newInstance(Context context) {
+ return new ConnectivityManagerShimImpl(context);
+ }
+ /**
+ * See android.net.ConnectivityManager#requestBackgroundNetwork
+ * @throws UnsupportedApiLevelException if API is not available in this API level.
+ */
+ @Override
+ public void requestBackgroundNetwork(@NonNull NetworkRequest request,
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler)
+ throws UnsupportedApiLevelException {
+ // Not supported for API 29.
+ throw new UnsupportedApiLevelException("Not supported in API 29.");
+ }
+
+ /**
+ * See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback
+ */
+ @Override
+ public void registerSystemDefaultNetworkCallback(@NonNull NetworkCallback networkCallback,
+ @NonNull Handler handler) {
+ // defaultNetworkRequest is not really a "request", just a way of tracking the system
+ // default network. It's guaranteed not to actually bring up any networks because it
+ // should be the same request as the ConnectivityService default request, and thus
+ // shares fate with it. In API <= R, registerSystemDefaultNetworkCallback is not
+ // available, and registerDefaultNetworkCallback will not track the system default when
+ // a VPN applies to the UID of this process.
+ final NetworkRequest defaultNetworkRequest = makeEmptyCapabilitiesRequest()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+ mCm.requestNetwork(defaultNetworkRequest, networkCallback, handler);
+ }
+
+ @NonNull
+ protected NetworkRequest.Builder makeEmptyCapabilitiesRequest() {
+ // Q does not have clearCapabilities(), so assume the default capabilities are as below
+ return new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .removeCapability(NET_CAPABILITY_NOT_VPN);
+ }
+}
diff --git a/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java b/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
index b655858..0b000a9 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
@@ -34,4 +34,12 @@
// Constants defined in android.net.ConnectivityDiagnosticsManager.
public static final int DETECTION_METHOD_DNS_EVENTS = 1;
public static final int DETECTION_METHOD_TCP_METRICS = 2;
+
+ // Constants defined in android.net.CaptivePortalData.
+ public static final int CAPTIVE_PORTAL_DATA_SOURCE_OTHER = 0;
+ public static final int CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT = 1;
+
+ // Constants defined in android.net.NetworkCapabilities.
+ public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
+
}
diff --git a/apishim/29/com/android/networkstack/apishim/api29/NetworkInformationShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/NetworkInformationShimImpl.java
index 8dc7b5c..e68020b 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/NetworkInformationShimImpl.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/NetworkInformationShimImpl.java
@@ -16,7 +16,6 @@
package com.android.networkstack.apishim.api29;
-import android.net.CaptivePortalData;
import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
@@ -121,10 +120,7 @@
* @param captivePortalData Captive portal data to be used
*/
public void setCaptivePortalData(@NonNull LinkProperties lp,
- @Nullable CaptivePortalData captivePortalData) {
- if (lp == null) {
- return;
- }
- lp.setCaptivePortalData(captivePortalData);
+ @Nullable CaptivePortalDataShim captivePortalData) {
+ // Not supported on this API level: no-op
}
}
diff --git a/apishim/29/com/android/networkstack/apishim/api29/NetworkRequestShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/NetworkRequestShimImpl.java
new file mode 100644
index 0000000..0c1d837
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/api29/NetworkRequestShimImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api29;
+
+import android.net.NetworkRequest;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+import java.util.Set;
+
+/**
+ * Implementation of {@link NetworkRequestShim} for API 29.
+ */
+public class NetworkRequestShimImpl implements NetworkRequestShim {
+ protected NetworkRequestShimImpl() {}
+
+ /**
+ * Get a new instance of {@link NetworkRequestShim}.
+ */
+ public static NetworkRequestShim newInstance() {
+ return new NetworkRequestShimImpl();
+ }
+
+ @Override
+ public void setUids(@NonNull NetworkRequest.Builder builder,
+ @Nullable Set<Range<Integer>> uids) throws UnsupportedApiLevelException {
+ // Not supported before API 31.
+ throw new UnsupportedApiLevelException("Not supported before API 31.");
+ }
+}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/CaptivePortalDataShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/CaptivePortalDataShimImpl.java
index 19a41db..5825021 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/CaptivePortalDataShimImpl.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/CaptivePortalDataShimImpl.java
@@ -39,10 +39,14 @@
@NonNull
protected final CaptivePortalData mData;
- protected CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
+ public CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
mData = data;
}
+ public CaptivePortalData getData() {
+ return mData;
+ }
+
/**
* Parse a {@link CaptivePortalDataShim} from a JSON object.
* @throws JSONException The JSON is not a representation of correct captive portal data.
@@ -116,4 +120,36 @@
public void notifyChanged(INetworkMonitorCallbacks cb) throws RemoteException {
cb.notifyCaptivePortalDataChanged(mData);
}
+
+ /**
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name set
+ *
+ * @param friendlyName The friendly name to set
+ * @return a {@link CaptivePortalDataShim} object with a friendly name set
+ */
+ @Override
+ public CaptivePortalDataShim withVenueFriendlyName(String friendlyName)
+ throws UnsupportedApiLevelException {
+ // Not supported in API level 29
+ throw new UnsupportedApiLevelException("FriendlyName not supported on API 30");
+ }
+
+ /**
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name and Passpoint external
+ * URLs set
+ *
+ * @param friendlyName The friendly name to set
+ * @param venueInfoUrl Venue information URL
+ * @param termsAndConditionsUrl Terms and conditions URL
+ *
+ * @return a {@link CaptivePortalDataShim} object with friendly name, venue info URL and terms
+ * and conditions URL set
+ */
+ @Override
+ public CaptivePortalDataShim withPasspointInfo(@NonNull String friendlyName,
+ @NonNull Uri venueInfoUrl, @NonNull Uri termsAndConditionsUrl)
+ throws UnsupportedApiLevelException {
+ // Not supported in API level 29
+ throw new UnsupportedApiLevelException("PasspointInfo not supported on API 30");
+ }
}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java
new file mode 100644
index 0000000..7c1d786
--- /dev/null
+++ b/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api30;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
+
+import android.content.Context;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkRequest;
+import android.os.Build;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+/**
+ * Implementation of {@link ConnectivityManagerShim} for API 30.
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+public class ConnectivityManagerShimImpl
+ extends com.android.networkstack.apishim.api29.ConnectivityManagerShimImpl {
+ protected ConnectivityManagerShimImpl(Context context) {
+ super(context);
+ }
+
+ /**
+ * Get a new instance of {@link ConnectivityManagerShim}.
+ */
+ @RequiresApi(Build.VERSION_CODES.Q)
+ public static ConnectivityManagerShim newInstance(Context context) {
+ if (!isAtLeastR()) {
+ return com.android.networkstack.apishim.api29.ConnectivityManagerShimImpl
+ .newInstance(context);
+ }
+ return new ConnectivityManagerShimImpl(context);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#requestBackgroundNetwork
+ * @throws UnsupportedApiLevelException if API is not available in this API level.
+ */
+ @Override
+ public void requestBackgroundNetwork(@NonNull NetworkRequest request,
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler)
+ throws UnsupportedApiLevelException {
+ // Not supported for API 30.
+ throw new UnsupportedApiLevelException("Not supported in API 30.");
+ }
+
+ @NonNull
+ @Override
+ protected NetworkRequest.Builder makeEmptyCapabilitiesRequest() {
+ return new NetworkRequest.Builder().clearCapabilities();
+ }
+}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/ConstantsShim.java b/apishim/30/com/android/networkstack/apishim/api30/ConstantsShim.java
index 27fd745..19ff9d3 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/ConstantsShim.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/ConstantsShim.java
@@ -38,8 +38,12 @@
public static final int DETECTION_METHOD_TCP_METRICS =
DataStallReport.DETECTION_METHOD_TCP_METRICS;
- /**
- * @see android.net.NetworkCapabilities
- */
+ // Constants defined in android.net.ConnectivityManager.
+ public static final int BLOCKED_REASON_NONE = 0;
+ public static final int BLOCKED_REASON_LOCKDOWN_VPN = 16;
+
+ // Constants defined in android.net.NetworkCapabilities.
+ public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
+ public static final int NET_CAPABILITY_ENTERPRISE = 29;
public static final int TRANSPORT_TEST = 7;
}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java
index 5d9b013..477dd42a 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java
@@ -21,6 +21,7 @@
import android.net.NetworkCapabilities;
import android.net.Uri;
import android.os.Build;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -37,6 +38,8 @@
*/
public class NetworkInformationShimImpl extends
com.android.networkstack.apishim.api29.NetworkInformationShimImpl {
+ private static final String TAG = "api30.NetworkInformationShimImpl";
+
protected NetworkInformationShimImpl() {}
/**
@@ -105,4 +108,20 @@
@NonNull Inet4Address serverAddress) {
lp.setDhcpServerAddress(serverAddress);
}
+
+ @Override
+ public void setCaptivePortalData(@NonNull LinkProperties lp,
+ @Nullable CaptivePortalDataShim captivePortalData) {
+ if (lp == null) {
+ return;
+ }
+ if (!(captivePortalData instanceof CaptivePortalDataShimImpl)) {
+ // The caller passed in a subclass that is not a CaptivePortalDataShimImpl.
+ // This is a programming error, but don't crash with ClassCastException.
+ Log.wtf(TAG, "Expected CaptivePortalDataShimImpl, but got "
+ + captivePortalData.getClass().getName());
+ return;
+ }
+ lp.setCaptivePortalData(((CaptivePortalDataShimImpl) captivePortalData).getData());
+ }
}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/NetworkRequestShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/NetworkRequestShimImpl.java
new file mode 100644
index 0000000..b65a556
--- /dev/null
+++ b/apishim/30/com/android/networkstack/apishim/api30/NetworkRequestShimImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api30;
+
+import android.os.Build;
+
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+import com.android.networkstack.apishim.common.ShimUtils;
+
+/**
+ * Implementation of {@link NetworkRequestShim} for API 30.
+ */
+public class NetworkRequestShimImpl
+ extends com.android.networkstack.apishim.api29.NetworkRequestShimImpl {
+ protected NetworkRequestShimImpl() {
+ super();
+ }
+
+ /**
+ * Get a new instance of {@link NetworkRequestShim}.
+ */
+ public static NetworkRequestShim newInstance() {
+ if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) {
+ return com.android.networkstack.apishim.api29.NetworkRequestShimImpl
+ .newInstance();
+ }
+ return new NetworkRequestShimImpl();
+ }
+}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/SettingsShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/SettingsShimImpl.java
new file mode 100644
index 0000000..b8188c6
--- /dev/null
+++ b/apishim/30/com/android/networkstack/apishim/api30/SettingsShimImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api30;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.networkstack.apishim.common.SettingsShim;
+
+/**
+ * Implementation of {@link SettingsShim} for API 30.
+ */
+public class SettingsShimImpl implements SettingsShim {
+ protected SettingsShimImpl() { }
+
+ /**
+ * Get a new instance of {@link SettingsShim}.
+ *
+ * Use com.android.networkstack.apishim.SeetingsShim#newInstance()
+ * (non-API30 version) instead, to use the correct shims depending on build SDK.
+ */
+ public static SettingsShim newInstance() {
+ return new SettingsShimImpl();
+ }
+
+ @Override
+ public boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @NonNull String callingPackage, @Nullable String callingAttributionTag,
+ boolean throwException) {
+ return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
+ throwException);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java b/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
deleted file mode 100644
index 955167d..0000000
--- a/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.networkstack.apishim;
-
-import android.net.CaptivePortalData;
-
-import androidx.annotation.NonNull;
-
-import com.android.networkstack.apishim.common.CaptivePortalDataShim;
-
-/**
- * Compatibility implementation of {@link CaptivePortalDataShim}.
- */
-public class CaptivePortalDataShimImpl
- extends com.android.networkstack.apishim.api30.CaptivePortalDataShimImpl {
- protected CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
- super(data);
- }
-
- @Override
- public String getVenueFriendlyName() {
- return mData.getVenueFriendlyName();
- }
-
- /**
- * Generate a {@link CaptivePortalData} object with a friendly name set
- *
- * @param friendlyName The friendly name to set
- * @return a {@link CaptivePortalData} object with a friendly name set
- */
- public CaptivePortalData withVenueFriendlyName(String friendlyName) {
- return new CaptivePortalData.Builder(mData)
- .setVenueFriendlyName(friendlyName)
- .build();
- }
-}
diff --git a/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
new file mode 100644
index 0000000..5ae006b
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.networkstack.apishim.api31;
+
+import android.net.CaptivePortalData;
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+
+import com.android.networkstack.apishim.common.CaptivePortalDataShim;
+
+/**
+ * Compatibility implementation of {@link CaptivePortalDataShim}.
+ */
+public class CaptivePortalDataShimImpl
+ extends com.android.networkstack.apishim.api30.CaptivePortalDataShimImpl {
+ public CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
+ super(data);
+ }
+
+ @Override
+ public CharSequence getVenueFriendlyName() {
+ return mData.getVenueFriendlyName();
+ }
+
+ /**
+ * Get the information source of the User portal
+ * @return The source that the User portal was obtained from
+ */
+ @Override
+ public int getUserPortalUrlSource() {
+ return mData.getUserPortalUrlSource();
+ }
+
+ /**
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name set
+ *
+ * @param friendlyName The friendly name to set
+ * @return a {@link CaptivePortalDataShim} object with a friendly name set
+ */
+ @Override
+ public CaptivePortalDataShim withVenueFriendlyName(String friendlyName) {
+ return new CaptivePortalDataShimImpl(new CaptivePortalData.Builder(mData)
+ .setVenueFriendlyName(friendlyName)
+ .build());
+ }
+
+ /**
+ * Generate a {@link CaptivePortalDataShim} object with a friendly name and Passpoint external
+ * URLs set
+ *
+ * @param friendlyName The friendly name to set
+ * @param venueInfoUrl Venue information URL
+ * @param termsAndConditionsUrl Terms and conditions URL
+ *
+ * @return a {@link CaptivePortalDataShim} object with friendly name, venue info URL and terms
+ * and conditions URL set
+ */
+ @Override
+ public CaptivePortalDataShim withPasspointInfo(@NonNull String friendlyName,
+ @NonNull Uri venueInfoUrl, @NonNull Uri termsAndConditionsUrl) {
+ return new CaptivePortalDataShimImpl(new CaptivePortalData.Builder(mData)
+ .setVenueFriendlyName(friendlyName)
+ .setVenueInfoUrl(venueInfoUrl, ConstantsShim.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
+ .setUserPortalUrl(termsAndConditionsUrl,
+ ConstantsShim.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT)
+ .build());
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
new file mode 100644
index 0000000..46de698
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api31;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
+
+import android.content.Context;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkRequest;
+import android.os.Build;
+import android.os.Handler;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+
+import java.util.Collection;
+
+/**
+ * Implementation of {@link ConnectivityManagerShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S)
+public class ConnectivityManagerShimImpl
+ extends com.android.networkstack.apishim.api30.ConnectivityManagerShimImpl {
+
+ protected ConnectivityManagerShimImpl(Context context) {
+ super(context);
+ }
+
+ /**
+ * Get a new instance of {@link ConnectivityManagerShim}.
+ */
+ @RequiresApi(Build.VERSION_CODES.Q)
+ public static ConnectivityManagerShim newInstance(Context context) {
+ if (!isAtLeastS()) {
+ return com.android.networkstack.apishim.api30.ConnectivityManagerShimImpl
+ .newInstance(context);
+ }
+ return new ConnectivityManagerShimImpl(context);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#requestBackgroundNetwork
+ */
+ @Override
+ public void requestBackgroundNetwork(@NonNull NetworkRequest request,
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
+ mCm.requestBackgroundNetwork(request, networkCallback, handler);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback
+ */
+ @Override
+ public void registerSystemDefaultNetworkCallback(
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
+ mCm.registerSystemDefaultNetworkCallback(networkCallback, handler);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#registerDefaultNetworkCallbackAsUid
+ */
+ @Override
+ public void registerDefaultNetworkCallbackForUid(
+ int uid, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
+ mCm.registerDefaultNetworkCallbackForUid(uid, networkCallback, handler);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#setLegacyLockdownVpnEnabled
+ */
+ @Override
+ public void setLegacyLockdownVpnEnabled(boolean enabled) {
+ mCm.setLegacyLockdownVpnEnabled(enabled);
+ }
+
+ /**
+ * See android.net.ConnectivityManager#setRequireVpnForUids
+ */
+ @Override
+ public void setRequireVpnForUids(boolean requireVpn, Collection<Range<Integer>> ranges) {
+ mCm.setRequireVpnForUids(requireVpn, ranges);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java b/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
similarity index 96%
rename from apishim/31/com/android/networkstack/apishim/ConstantsShim.java
rename to apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
index 0184845..95ff072 100644
--- a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import androidx.annotation.VisibleForTesting;
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
similarity index 83%
rename from apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
index d668d7e..a5c9a71 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.os.Build;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import com.android.networkstack.apishim.common.CaptivePortalDataShim;
@@ -48,7 +50,7 @@
if (!useApiAboveR()) {
return com.android.networkstack.apishim.api30.NetworkInformationShimImpl.newInstance();
}
- return new com.android.networkstack.apishim.NetworkInformationShimImpl();
+ return new NetworkInformationShimImpl();
}
@Nullable
@@ -57,4 +59,11 @@
if (lp == null || lp.getCaptivePortalData() == null) return null;
return new CaptivePortalDataShimImpl(lp.getCaptivePortalData());
}
+
+ @RequiresApi(Build.VERSION_CODES.S)
+ @Nullable
+ @Override
+ public String getCapabilityCarrierName(int capability) {
+ return NetworkCapabilities.getCapabilityCarrierName(capability);
+ }
}
diff --git a/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
new file mode 100644
index 0000000..2dc5d72
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api31;
+
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
+
+import android.net.NetworkRequest;
+import android.os.Build;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+
+import java.util.Set;
+
+/**
+ * Implementation of {@link NetworkRequestShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S)
+public class NetworkRequestShimImpl
+ extends com.android.networkstack.apishim.api30.NetworkRequestShimImpl {
+ protected NetworkRequestShimImpl() {
+ super();
+ }
+
+ /**
+ * Get a new instance of {@link NetworkRequestShim}.
+ */
+ @RequiresApi(Build.VERSION_CODES.Q)
+ public static NetworkRequestShim newInstance() {
+ if (!isAtLeastS()) {
+ return com.android.networkstack.apishim.api30.NetworkRequestShimImpl.newInstance();
+ }
+ return new NetworkRequestShimImpl();
+ }
+
+ @Override
+ public void setUids(@NonNull NetworkRequest.Builder builder,
+ @Nullable Set<Range<Integer>> uids) {
+ builder.setUids(uids);
+ }
+
+ @Override
+ public NetworkRequest.Builder setIncludeOtherUidNetworks(NetworkRequest.Builder builder,
+ boolean include) {
+ builder.setIncludeOtherUidNetworks(include);
+ return builder;
+ }
+
+ @Override
+ public NetworkRequest.Builder newBuilder(@NonNull NetworkRequest request) {
+ return new NetworkRequest.Builder(request);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
similarity index 95%
rename from apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
index 0c92391..eda8e27 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.net.Network;
diff --git a/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
new file mode 100644
index 0000000..1b5cbae
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api31;
+
+import android.content.Context;
+import android.os.Build;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.networkstack.apishim.common.SettingsShim;
+import com.android.networkstack.apishim.common.ShimUtils;
+
+/**
+ * Implementation of {@link SettingsShim} for API 31.
+ */
+public class SettingsShimImpl
+ extends com.android.networkstack.apishim.api30.SettingsShimImpl {
+ protected SettingsShimImpl() { }
+
+ /**
+ * Get a new instance of {@link SettingsShim}.
+ */
+ public static SettingsShim newInstance() {
+ if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.R)) {
+ return com.android.networkstack.apishim.api30.SettingsShimImpl
+ .newInstance();
+ }
+ return new SettingsShimImpl();
+ }
+
+ @Override
+ public boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @NonNull String callingPackage, @Nullable String callingAttributionTag,
+ boolean throwException) {
+ return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
+ callingAttributionTag, throwException);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
similarity index 94%
rename from apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
index 483bde0..f5aa80b 100644
--- a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
/**
* Implementation of {@link NetworkShim} for API 30.
diff --git a/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java b/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
new file mode 100644
index 0000000..2056b1b
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.net.CaptivePortalData;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.CaptivePortalDataShim;
+
+/**
+ * Compatibility implementation of {@link CaptivePortalDataShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class CaptivePortalDataShimImpl
+ extends com.android.networkstack.apishim.api31.CaptivePortalDataShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ public CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
+ super(data);
+ }
+}
diff --git a/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java b/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
new file mode 100644
index 0000000..a7aa0c8
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.content.Context;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+
+/**
+ * Compatibility implementation of {@link ConnectivityManagerShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class ConnectivityManagerShimImpl
+ extends com.android.networkstack.apishim.api31.ConnectivityManagerShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected ConnectivityManagerShimImpl(Context context) {
+ super(context);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java b/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
similarity index 76%
copy from apishim/31/com/android/networkstack/apishim/ConstantsShim.java
copy to apishim/32/com/android/networkstack/apishim/ConstantsShim.java
index 0184845..0a5b555 100644
--- a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
+++ b/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
/**
* Utility class for defining and importing constants from the Android platform.
*/
-public class ConstantsShim extends com.android.networkstack.apishim.api30.ConstantsShim {
+public class ConstantsShim extends com.android.networkstack.apishim.api31.ConstantsShim {
/**
* Constant that callers can use to determine what version of the shim they are using.
* Must be the same as the version of the shims.
@@ -29,9 +29,5 @@
* the shimmed objects and methods themselves.
*/
@VisibleForTesting
- public static final int VERSION = 31;
-
- // When removing this shim, the version in NetworkMonitorUtils should be removed too.
- // TODO: add TRANSPORT_TEST to system API in API 31 (it is only a test API as of R)
- public static final int TRANSPORT_TEST = 7;
+ public static final int VERSION = 32;
}
diff --git a/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java
new file mode 100644
index 0000000..28aa75c
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.NetworkInformationShim;
+
+/**
+ * Compatibility implementation of {@link NetworkInformationShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class NetworkInformationShimImpl
+ extends com.android.networkstack.apishim.api31.NetworkInformationShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected NetworkInformationShimImpl() {}
+}
diff --git a/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java
new file mode 100644
index 0000000..95ae5ba
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+
+/**
+ * Implementation of {@link NetworkRequestShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class NetworkRequestShimImpl
+ extends com.android.networkstack.apishim.api31.NetworkRequestShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected NetworkRequestShimImpl() {
+ super();
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
similarity index 70%
copy from apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
copy to apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
index 0c92391..2e31a78 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
+++ b/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,14 +17,17 @@
package com.android.networkstack.apishim;
import android.net.Network;
+import android.os.Build;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
/**
- * Implementation of {@link NetworkShim} for API 30.
+ * Compatibility implementation of {@link com.android.networkstack.apishim.common.NetworkShim}.
*/
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
public class NetworkShimImpl extends com.android.networkstack.apishim.api30.NetworkShimImpl {
- // Currently, this is the same as the API 30 shim, so inherit everything from that.
+ // Currently, this is the same as the API 31 shim, so inherit everything from that.
protected NetworkShimImpl(@NonNull Network network) {
super(network);
}
diff --git a/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java b/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java
new file mode 100644
index 0000000..46d2102
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.SettingsShim;
+
+/**
+ * Compatibility implementation of {@link SettingsShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class SettingsShimImpl
+ extends com.android.networkstack.apishim.api30.SettingsShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected SettingsShimImpl() { }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
similarity index 68%
copy from apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
copy to apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
index 483bde0..2f4e500 100644
--- a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
+++ b/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,16 @@
package com.android.networkstack.apishim;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
/**
- * Implementation of {@link NetworkShim} for API 30.
+ * Implementation of {@link com.android.networkstack.apishim.common.SocketUtilsShim}.
*/
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
public class SocketUtilsShimImpl
extends com.android.networkstack.apishim.api30.SocketUtilsShimImpl {
- // Currently, this is the same as the API 30 shim, so inherit everything from that.
+ // Currently, this is the same as the API 31 shim, so inherit everything from that.
protected SocketUtilsShimImpl() {}
}
diff --git a/apishim/common/com/android/networkstack/apishim/common/CaptivePortalDataShim.java b/apishim/common/com/android/networkstack/apishim/common/CaptivePortalDataShim.java
index 4bd5532..13bf257 100644
--- a/apishim/common/com/android/networkstack/apishim/common/CaptivePortalDataShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/CaptivePortalDataShim.java
@@ -16,12 +16,12 @@
package com.android.networkstack.apishim.common;
-import android.annotation.NonNull;
-import android.net.CaptivePortalData;
import android.net.INetworkMonitorCallbacks;
import android.net.Uri;
import android.os.RemoteException;
+import androidx.annotation.NonNull;
+
/**
* Compatibility interface for {@link android.net.CaptivePortalData}.
*/
@@ -54,7 +54,12 @@
/**
* @see CaptivePortalData#getVenueFriendlyName()
*/
- String getVenueFriendlyName();
+ CharSequence getVenueFriendlyName();
+
+ /**
+ * @see CaptivePortalData#getUserPortalUrlSource()
+ */
+ int getUserPortalUrlSource();
/**
* @see INetworkMonitorCallbacks#notifyCaptivePortalDataChanged(android.net.CaptivePortalData)
@@ -65,7 +70,25 @@
* Generate a {@link CaptivePortalData} object with a friendly name set
*
* @param friendlyName The friendly name to set
+ * @throws UnsupportedApiLevelException when used with API level lower than 31
* @return a {@link CaptivePortalData} object with a friendly name set
*/
- CaptivePortalData withVenueFriendlyName(@NonNull String friendlyName);
+ CaptivePortalDataShim withVenueFriendlyName(@NonNull String friendlyName)
+ throws UnsupportedApiLevelException;
+
+ /**
+ * Generate a {@link CaptivePortalData} object with a friendly name and Passpoint external URLs
+ * set
+ *
+ * @param friendlyName The friendly name to set
+ * @param venueInfoUrl Venue information URL
+ * @param termsAndConditionsUrl Terms and conditions URL
+ *
+ * @throws UnsupportedApiLevelException when used with API level lower than 31
+ * @return a {@link CaptivePortalData} object with friendly name, venue info URL and terms
+ * and conditions URL set
+ */
+ CaptivePortalDataShim withPasspointInfo(@NonNull String friendlyName,
+ @NonNull Uri venueInfoUrl, @NonNull Uri termsAndConditionsUrl)
+ throws UnsupportedApiLevelException;
}
diff --git a/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java b/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java
new file mode 100644
index 0000000..86d785e
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.common;
+
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkRequest;
+import android.os.Handler;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+
+import java.util.Collection;
+
+/**
+ * Interface used to access API methods in {@link android.net.ConnectivityManager}, with
+ * appropriate fallbacks if the methods are not yet part of the released API.
+ *
+ * <p>This interface makes it easier for callers to use ConnectivityManagerShimImpl, as it's more
+ * obvious what methods must be implemented on each API level, and it abstracts from callers the
+ * need to reference classes that have different implementations (which also does not work well
+ * with IDEs).
+ */
+public interface ConnectivityManagerShim {
+ /** See android.net.ConnectivityManager#requestBackgroundNetwork */
+ void requestBackgroundNetwork(@NonNull NetworkRequest request,
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler)
+ throws UnsupportedApiLevelException;
+
+ /** See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback */
+ void registerSystemDefaultNetworkCallback(
+ @NonNull NetworkCallback networkCallback, @NonNull Handler handler);
+
+ /** See android.net.ConnectivityManager#registerDefaultNetworkCallbackForUid */
+ default void registerDefaultNetworkCallbackForUid(
+ int uid, @NonNull NetworkCallback networkCallback, @NonNull Handler handler)
+ throws UnsupportedApiLevelException {
+ throw new UnsupportedApiLevelException("Only supported starting from API 31");
+ }
+
+ /** See android.net.ConnectivityManager#setLegacyLockdownVpnEnabled */
+ default void setLegacyLockdownVpnEnabled(boolean enabled) throws UnsupportedApiLevelException {
+ throw new UnsupportedApiLevelException("Only supported starting from API 31");
+ }
+
+ /** See android.net.ConnectivityManager#setRequireVpnForUids */
+ default void setRequireVpnForUids(boolean requireVpn, Collection<Range<Integer>> ranges)
+ throws UnsupportedApiLevelException {
+ throw new UnsupportedApiLevelException("Only supported starting from API 31");
+ }
+}
diff --git a/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java b/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java
index 6cdcf8c..7fa1777 100644
--- a/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/NetworkInformationShim.java
@@ -16,7 +16,6 @@
package com.android.networkstack.apishim.common;
-import android.net.CaptivePortalData;
import android.net.IpPrefix;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
@@ -83,5 +82,18 @@
* @param captivePortalData Captive portal data to be used
*/
void setCaptivePortalData(@NonNull LinkProperties lp,
- @Nullable CaptivePortalData captivePortalData);
+ @Nullable CaptivePortalDataShim captivePortalData);
+
+ /**
+ * Get the name of the given capability that carriers use.
+ * If the capability does not have a carrier-name, returns null.
+ *
+ * @param capability The capability to get the carrier-name of.
+ * @return The carrier-name of the capability, or null if it doesn't exist.
+ * @hide
+ */
+ @Nullable
+ default String getCapabilityCarrierName(int capability) {
+ return null;
+ }
}
diff --git a/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
new file mode 100644
index 0000000..d07d1ae
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.common;
+
+import android.net.NetworkRequest;
+import android.util.Range;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Set;
+
+/**
+ * Interface used to access API methods in {@link android.net.NetworkRequest}, with
+ * appropriate fallbacks if the methods are not yet part of the released API.
+ */
+public interface NetworkRequestShim {
+ /**
+ * See android.net.NetworkRequest.Builder#setUids.
+ * Set the {@code uids} into {@code builder}.
+ */
+ void setUids(@NonNull NetworkRequest.Builder builder,
+ @Nullable Set<Range<Integer>> uids) throws UnsupportedApiLevelException;
+
+ /**
+ * See android.net.NetworkRequest.Builder#setIncludeOtherUidNetworks.
+ */
+ default NetworkRequest.Builder setIncludeOtherUidNetworks(NetworkRequest.Builder builder,
+ boolean include) throws UnsupportedApiLevelException {
+ throw new UnsupportedApiLevelException("Not supported before API 31.");
+ }
+
+ /**
+ * See android.net.NetworkRequest.Builder(NetworkRequest).
+ * @throws UnsupportedApiLevelException if API is not available in the API level.
+ */
+ default NetworkRequest.Builder newBuilder(@NonNull NetworkRequest request)
+ throws UnsupportedApiLevelException {
+ // Not supported before API 31.
+ throw new UnsupportedApiLevelException("Not supported before API 31.");
+ }
+}
diff --git a/apishim/common/com/android/networkstack/apishim/common/SettingsShim.java b/apishim/common/com/android/networkstack/apishim/common/SettingsShim.java
new file mode 100644
index 0000000..2453084
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/SettingsShim.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.common;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Interce for accessing API methods in {@link android.provider.Settings} by different API level.
+ */
+public interface SettingsShim {
+ /**
+ * @see android.provider.Settings#checkAndNoteWriteSettingsOperation(Context, int, String,
+ * String, boolean)
+ */
+ boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @NonNull String callingPackage, @Nullable String callingAttributionTag,
+ boolean throwException);
+}
diff --git a/apishim/jarjar-rules-compat.txt b/apishim/jarjar-rules-compat.txt
index dba2b49..4f34ccb 100644
--- a/apishim/jarjar-rules-compat.txt
+++ b/apishim/jarjar-rules-compat.txt
@@ -1,7 +1,7 @@
# jarjar rules to use on API stable builds.
# Use the latest stable apishim package as the main apishim package, to replace and avoid building
# the unstable, non-compatibility shims.
-# Once API 31 is stable, apishim/31/com.android.networkstack.apishim should be moved to the
-# com.android.networkstack.apishim.api31 package, a new apishim/32/com.android.networkstack.apishim
-# package should be created, and this rule should reference api31.
-rule com.android.networkstack.apishim.api30.** com.android.networkstack.apishim.@1
\ No newline at end of file
+# Once API 32 is stable, apishim/32/com.android.networkstack.apishim should be moved to the
+# com.android.networkstack.apishim.api32 package, a new apishim/33/com.android.networkstack.apishim
+# package should be created, and this rule should reference api32.
+rule com.android.networkstack.apishim.api31.** com.android.networkstack.apishim.@1
\ No newline at end of file
diff --git a/common/captiveportal/Android.bp b/common/captiveportal/Android.bp
index 0b49eb2..876e733 100644
--- a/common/captiveportal/Android.bp
+++ b/common/captiveportal/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_library {
name: "captiveportal-lib",
srcs: ["src/**/*.java"],
@@ -23,4 +27,4 @@
sdk_version: "system_current",
// this is part of updatable modules(NetworkStack) which targets 29(Q)
min_sdk_version: "29",
-}
\ No newline at end of file
+}
diff --git a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
index 2ba1dcc..8b388ad 100755
--- a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
+++ b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -103,11 +103,22 @@
}
public boolean isSuccessful() {
- return mHttpResponseCode == SUCCESS_CODE;
+ return isSuccessCode(mHttpResponseCode);
}
public boolean isPortal() {
- return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
+ return isPortalCode(mHttpResponseCode);
+ }
+
+ private static boolean isSuccessCode(int responseCode) {
+ return responseCode == SUCCESS_CODE;
+ }
+
+ /**
+ * @return Whether the specified HTTP return code indicates a captive portal.
+ */
+ public static boolean isPortalCode(int responseCode) {
+ return !isSuccessCode(responseCode) && (responseCode >= 200) && (responseCode <= 399);
}
public boolean isFailed() {
diff --git a/common/moduleutils/Android.bp b/common/moduleutils/Android.bp
index 644b0a4..d90c33d 100644
--- a/common/moduleutils/Android.bp
+++ b/common/moduleutils/Android.bp
@@ -17,21 +17,18 @@
// Shared utility sources to be used by multiple network modules
// TODO: remove all frameworks/base dependencies on packages/modules/NetworkStack and
// frameworks/base/packages/Tethering by moving these files to frameworks/libs/net.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+// TODO: remove this filegroup together with services.net
filegroup {
name: "net-module-utils-srcs",
srcs: [
- "src/android/net/util/SharedLog.java",
- "src/android/net/shared/InitialConfiguration.java",
- "src/android/net/shared/Layer2Information.java",
- "src/android/net/shared/LinkPropertiesParcelableUtil.java",
- "src/android/net/shared/ParcelableUtil.java",
"src/android/net/shared/NetdUtils.java",
- "src/android/net/shared/NetworkMonitorUtils.java",
- "src/android/net/shared/ParcelableUtil.java",
- "src/android/net/shared/PrivateDnsConfig.java",
- "src/android/net/shared/ProvisioningConfiguration.java",
"src/android/net/shared/RouteUtils.java",
"src/android/net/util/InterfaceParams.java",
+ "src/android/net/util/SharedLog.java",
],
visibility: [
"//frameworks/base/services/net",
@@ -39,6 +36,19 @@
}
filegroup {
+ name: "connectivity-module-utils-srcs",
+ srcs: [
+ "src/android/net/util/SharedLog.java",
+ "src/android/net/shared/NetdUtils.java",
+ "src/android/net/shared/NetworkMonitorUtils.java",
+ "src/android/net/shared/RouteUtils.java",
+ ],
+ visibility: [
+ "//packages/modules/Connectivity/service",
+ ]
+}
+
+filegroup {
name: "networkstack-module-utils-srcs",
srcs: ["src/**/*.java"],
visibility: [
@@ -54,7 +64,6 @@
"src/android/net/ip/InterfaceController.java",
"src/android/net/ip/IpNeighborMonitor.java",
"src/android/net/ip/NetlinkMonitor.java",
- "src/android/net/netlink/*.java",
"src/android/net/shared/NetdUtils.java",
"src/android/net/shared/RouteUtils.java",
"src/android/net/util/InterfaceParams.java",
diff --git a/common/moduleutils/src/android/net/ip/ConntrackMonitor.java b/common/moduleutils/src/android/net/ip/ConntrackMonitor.java
index 9189002..43005cd 100644
--- a/common/moduleutils/src/android/net/ip/ConntrackMonitor.java
+++ b/common/moduleutils/src/android/net/ip/ConntrackMonitor.java
@@ -16,12 +16,9 @@
package android.net.ip;
-import static android.net.netlink.ConntrackMessage.DYING_MASK;
-import static android.net.netlink.ConntrackMessage.ESTABLISHED_MASK;
+import static com.android.net.module.util.netlink.ConntrackMessage.DYING_MASK;
+import static com.android.net.module.util.netlink.ConntrackMessage.ESTABLISHED_MASK;
-import android.net.netlink.ConntrackMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkMessage;
import android.net.util.SharedLog;
import android.os.Handler;
import android.system.OsConstants;
@@ -29,6 +26,9 @@
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.netlink.ConntrackMessage;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkMessage;
import java.util.Objects;
@@ -51,6 +51,12 @@
public static final int NF_NETLINK_CONNTRACK_UPDATE = 2;
public static final int NF_NETLINK_CONNTRACK_DESTROY = 4;
+ // The socket receive buffer size in bytes. If too many conntrack messages are sent too
+ // quickly, the conntrack messages can overflow the socket receive buffer. This can happen
+ // if too many connections are disconnected by losing network and so on. Use a large-enough
+ // buffer to avoid the error ENOBUFS while listening to the conntrack messages.
+ private static final int SOCKET_RECV_BUFSIZE = 6 * 1024 * 1024;
+
/**
* A class for describing parsed netfilter conntrack events.
*/
@@ -176,7 +182,7 @@
public ConntrackMonitor(@NonNull Handler h, @NonNull SharedLog log,
@NonNull ConntrackEventConsumer cb) {
super(h, log, TAG, OsConstants.NETLINK_NETFILTER, NF_NETLINK_CONNTRACK_NEW
- | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
+ | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY, SOCKET_RECV_BUFSIZE);
mConsumer = cb;
}
diff --git a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
index b45c061..a16fdf2 100644
--- a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
+++ b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
@@ -16,22 +16,24 @@
package android.net.ip;
-import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
-import static android.net.netlink.NetlinkConstants.hexify;
-import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
import static android.system.OsConstants.NETLINK_ROUTE;
+import static com.android.net.module.util.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static com.android.net.module.util.netlink.NetlinkConstants.hexify;
+import static com.android.net.module.util.netlink.NetlinkConstants.stringForNlMsgType;
+
import android.net.MacAddress;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNdMsg;
import android.net.util.SharedLog;
import android.os.Handler;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.NetlinkSocket;
+import com.android.net.module.util.netlink.RtNetlinkNeighborMessage;
+import com.android.net.module.util.netlink.StructNdMsg;
+
import java.net.InetAddress;
import java.util.StringJoiner;
diff --git a/common/moduleutils/src/android/net/ip/NetlinkMonitor.java b/common/moduleutils/src/android/net/ip/NetlinkMonitor.java
index 3d314f1..17157d8 100644
--- a/common/moduleutils/src/android/net/ip/NetlinkMonitor.java
+++ b/common/moduleutils/src/android/net/ip/NetlinkMonitor.java
@@ -16,16 +16,16 @@
package android.net.ip;
-import static android.net.netlink.NetlinkConstants.hexify;
import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
import static android.system.OsConstants.AF_NETLINK;
import static android.system.OsConstants.SOCK_DGRAM;
import static android.system.OsConstants.SOCK_NONBLOCK;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_RCVBUF;
+
+import static com.android.net.module.util.netlink.NetlinkConstants.hexify;
import android.annotation.NonNull;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.NetlinkSocket;
import android.net.util.SharedLog;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -35,6 +35,9 @@
import android.util.Log;
import com.android.net.module.util.PacketReader;
+import com.android.net.module.util.netlink.NetlinkErrorMessage;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.NetlinkSocket;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -56,9 +59,13 @@
protected final String mTag;
private final int mFamily;
private final int mBindGroups;
+ private final int mSockRcvbufSize;
private static final boolean DBG = false;
+ // Default socket receive buffer size. This means the specific buffer size is not set.
+ private static final int DEFAULT_SOCKET_RECV_BUFSIZE = -1;
+
/**
* Constructs a new {@code NetlinkMonitor} instance.
*
@@ -68,14 +75,23 @@
* @param tag The log tag to use for log messages.
* @param family the Netlink socket family to, e.g., {@code NETLINK_ROUTE}.
* @param bindGroups the netlink groups to bind to.
+ * @param sockRcvbufSize the specific socket receive buffer size in bytes. -1 means that don't
+ * set the specific socket receive buffer size in #createFd and use the default value in
+ * /proc/sys/net/core/rmem_default file. See SO_RCVBUF in man-pages/socket.
*/
public NetlinkMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull String tag,
- int family, int bindGroups) {
+ int family, int bindGroups, int sockRcvbufSize) {
super(h, NetlinkSocket.DEFAULT_RECV_BUFSIZE);
mLog = log.forSubComponent(tag);
mTag = tag;
mFamily = family;
mBindGroups = bindGroups;
+ mSockRcvbufSize = sockRcvbufSize;
+ }
+
+ public NetlinkMonitor(@NonNull Handler h, @NonNull SharedLog log, @NonNull String tag,
+ int family, int bindGroups) {
+ this(h, log, tag, family, bindGroups, DEFAULT_SOCKET_RECV_BUFSIZE);
}
@Override
@@ -84,6 +100,9 @@
try {
fd = Os.socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, mFamily);
+ if (mSockRcvbufSize != DEFAULT_SOCKET_RECV_BUFSIZE) {
+ Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, mSockRcvbufSize);
+ }
Os.bind(fd, makeNetlinkSocketAddress(0, mBindGroups));
NetlinkSocket.connectToKernel(fd);
diff --git a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
index 981a576..b151cb9 100644
--- a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
+++ b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
@@ -19,6 +19,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -27,6 +28,8 @@
import android.net.NetworkCapabilities;
+import com.android.modules.utils.build.SdkLevel;
+
/** @hide */
public class NetworkMonitorUtils {
// This class is used by both NetworkMonitor and ConnectivityService, so it cannot use
@@ -36,6 +39,14 @@
// TODO: use NetworkCapabilities.TRANSPORT_TEST once NetworkStack builds against API 31.
private static final int TRANSPORT_TEST = 7;
+ // This class is used by both NetworkMonitor and ConnectivityService, so it cannot use
+ // NetworkStack shims, but at the same time cannot use non-system APIs.
+ // NET_CAPABILITY_NOT_VCN_MANAGED is system API as of S (so it is enforced to always be 28 and
+ // can't be changed).
+ // TODO: use NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED once NetworkStack builds against
+ // API 31.
+ public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
+
// Network conditions broadcast constants
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
@@ -59,18 +70,19 @@
public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) {
if (nc == null) return false;
+ final boolean isVcnManaged = SdkLevel.isAtLeastS()
+ && !nc.hasCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ final boolean isOemPaid = nc.hasCapability(NET_CAPABILITY_OEM_PAID)
+ && nc.hasCapability(NET_CAPABILITY_TRUSTED);
+ final boolean isDefaultCapable = nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ && nc.hasCapability(NET_CAPABILITY_TRUSTED);
+
// TODO: Consider requiring validation for DUN networks.
if (nc.hasCapability(NET_CAPABILITY_INTERNET)
- && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED)) {
- // Real networks
+ && (isVcnManaged || isOemPaid || isDefaultCapable)) {
return true;
}
- // TODO: once TRANSPORT_TEST is @SystemApi in S and S SDK is stable (so constant shims can
- // be replaced with the SDK constant that will be inlined), replace isTestNetwork with
- // hasTransport(TRANSPORT_TEST)
-
// Test networks that also have one of the major transport types are attempting to replicate
// that transport on a test interface (for example, test ethernet networks with
// EthernetManager#setIncludeTestInterfaces). Run validation on them for realistic tests.
diff --git a/common/netlinkclient/Android.bp b/common/netlinkclient/Android.bp
deleted file mode 100644
index 2b4a2d6..0000000
--- a/common/netlinkclient/Android.bp
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (C) 2018 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.
-//
-
-java_library {
- name: "netlink-client",
- srcs: [
- "src/**/*.java",
- ":framework-annotations",
- ],
- libs: [
- "androidx.annotation_annotation",
- ],
- sdk_version: "system_current",
- // this is part of updatable modules(NetworkStack) which targets 29(Q)
- min_sdk_version: "29",
-}
diff --git a/common/netlinkclient/src/android/net/netlink/ConntrackMessage.java b/common/netlinkclient/src/android/net/netlink/ConntrackMessage.java
deleted file mode 100644
index cc8bb7e..0000000
--- a/common/netlinkclient/src/android/net/netlink/ConntrackMessage.java
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (C) 2017 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.netlink;
-
-import static android.net.netlink.StructNlAttr.findNextAttrOfType;
-import static android.net.netlink.StructNlAttr.makeNestedType;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.system.OsConstants;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-
-/**
- * A NetlinkMessage subclass for netlink conntrack messages.
- *
- * see also: <linux_src>/include/uapi/linux/netfilter/nfnetlink_conntrack.h
- *
- * @hide
- */
-public class ConntrackMessage extends NetlinkMessage {
- public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
-
- // enum ctattr_type
- public static final short CTA_TUPLE_ORIG = 1;
- public static final short CTA_TUPLE_REPLY = 2;
- public static final short CTA_STATUS = 3;
- public static final short CTA_TIMEOUT = 7;
-
- // enum ctattr_tuple
- public static final short CTA_TUPLE_IP = 1;
- public static final short CTA_TUPLE_PROTO = 2;
-
- // enum ctattr_ip
- public static final short CTA_IP_V4_SRC = 1;
- public static final short CTA_IP_V4_DST = 2;
-
- // enum ctattr_l4proto
- public static final short CTA_PROTO_NUM = 1;
- public static final short CTA_PROTO_SRC_PORT = 2;
- public static final short CTA_PROTO_DST_PORT = 3;
-
- // enum ip_conntrack_status
- public static final int IPS_EXPECTED = 0x00000001;
- public static final int IPS_SEEN_REPLY = 0x00000002;
- public static final int IPS_ASSURED = 0x00000004;
- public static final int IPS_CONFIRMED = 0x00000008;
- public static final int IPS_SRC_NAT = 0x00000010;
- public static final int IPS_DST_NAT = 0x00000020;
- public static final int IPS_SEQ_ADJUST = 0x00000040;
- public static final int IPS_SRC_NAT_DONE = 0x00000080;
- public static final int IPS_DST_NAT_DONE = 0x00000100;
- public static final int IPS_DYING = 0x00000200;
- public static final int IPS_FIXED_TIMEOUT = 0x00000400;
- public static final int IPS_TEMPLATE = 0x00000800;
- public static final int IPS_UNTRACKED = 0x00001000;
- public static final int IPS_HELPER = 0x00002000;
- public static final int IPS_OFFLOAD = 0x00004000;
- public static final int IPS_HW_OFFLOAD = 0x00008000;
-
- // ip_conntrack_status mask
- // Interesting on the NAT conntrack session which has already seen two direction traffic.
- // TODO: Probably IPS_{SRC, DST}_NAT_DONE are also interesting.
- public static final int ESTABLISHED_MASK = IPS_CONFIRMED | IPS_ASSURED | IPS_SEEN_REPLY
- | IPS_SRC_NAT;
- // Interesting on the established NAT conntrack session which is dying.
- public static final int DYING_MASK = ESTABLISHED_MASK | IPS_DYING;
-
- /**
- * A tuple for the conntrack connection information.
- *
- * see also CTA_TUPLE_ORIG and CTA_TUPLE_REPLY.
- */
- public static class Tuple {
- public final Inet4Address srcIp;
- public final Inet4Address dstIp;
-
- // Both port and protocol number are unsigned numbers stored in signed integers, and that
- // callers that want to compare them to integers should either cast those integers, or
- // convert them to unsigned using Byte.toUnsignedInt() and Short.toUnsignedInt().
- public final short srcPort;
- public final short dstPort;
- public final byte protoNum;
-
- public Tuple(TupleIpv4 ip, TupleProto proto) {
- this.srcIp = ip.src;
- this.dstIp = ip.dst;
- this.srcPort = proto.srcPort;
- this.dstPort = proto.dstPort;
- this.protoNum = proto.protoNum;
- }
-
- @Override
- @VisibleForTesting
- public boolean equals(Object o) {
- if (!(o instanceof Tuple)) return false;
- Tuple that = (Tuple) o;
- return Objects.equals(this.srcIp, that.srcIp)
- && Objects.equals(this.dstIp, that.dstIp)
- && this.srcPort == that.srcPort
- && this.dstPort == that.dstPort
- && this.protoNum == that.protoNum;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(srcIp, dstIp, srcPort, dstPort, protoNum);
- }
-
- @Override
- public String toString() {
- final String srcIpStr = (srcIp == null) ? "null" : srcIp.getHostAddress();
- final String dstIpStr = (dstIp == null) ? "null" : dstIp.getHostAddress();
- final String protoStr = NetlinkConstants.stringForProtocol(protoNum);
-
- return "Tuple{"
- + protoStr + ": "
- + srcIpStr + ":" + Short.toUnsignedInt(srcPort) + " -> "
- + dstIpStr + ":" + Short.toUnsignedInt(dstPort)
- + "}";
- }
- }
-
- /**
- * A tuple for the conntrack connection address.
- *
- * see also CTA_TUPLE_IP.
- */
- public static class TupleIpv4 {
- public final Inet4Address src;
- public final Inet4Address dst;
-
- public TupleIpv4(Inet4Address src, Inet4Address dst) {
- this.src = src;
- this.dst = dst;
- }
- }
-
- /**
- * A tuple for the conntrack connection protocol.
- *
- * see also CTA_TUPLE_PROTO.
- */
- public static class TupleProto {
- public final byte protoNum;
- public final short srcPort;
- public final short dstPort;
-
- public TupleProto(byte protoNum, short srcPort, short dstPort) {
- this.protoNum = protoNum;
- this.srcPort = srcPort;
- this.dstPort = dstPort;
- }
- }
-
- public static byte[] newIPv4TimeoutUpdateRequest(
- int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
- // *** STYLE WARNING ***
- //
- // Code below this point uses extra block indentation to highlight the
- // packing of nested tuple netlink attribute types.
- final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
- new StructNlAttr(CTA_TUPLE_IP,
- new StructNlAttr(CTA_IP_V4_SRC, src),
- new StructNlAttr(CTA_IP_V4_DST, dst)),
- new StructNlAttr(CTA_TUPLE_PROTO,
- new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
- new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
- new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
-
- final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
-
- final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
- final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final ConntrackMessage ctmsg = new ConntrackMessage();
- ctmsg.mHeader.nlmsg_len = bytes.length;
- ctmsg.mHeader.nlmsg_type = (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8)
- | NetlinkConstants.IPCTNL_MSG_CT_NEW;
- ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- ctmsg.mHeader.nlmsg_seq = 1;
- ctmsg.pack(byteBuffer);
-
- ctaTupleOrig.pack(byteBuffer);
- ctaTimeout.pack(byteBuffer);
-
- return bytes;
- }
-
- /**
- * Parses a netfilter conntrack message from a {@link ByteBuffer}.
- *
- * @param header the netlink message header.
- * @param byteBuffer The buffer from which to parse the netfilter conntrack message.
- * @return the parsed netfilter conntrack message, or {@code null} if the netfilter conntrack
- * message could not be parsed successfully (for example, if it was truncated).
- */
- public static ConntrackMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- // Just build the netlink header and netfilter header for now and pretend the whole message
- // was consumed.
- // TODO: Parse the conntrack attributes.
- final StructNfGenMsg nfGenMsg = StructNfGenMsg.parse(byteBuffer);
- if (nfGenMsg == null) {
- return null;
- }
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_STATUS, byteBuffer);
- int status = 0;
- if (nlAttr != null) {
- status = nlAttr.getValueAsBe32(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(CTA_TIMEOUT, byteBuffer);
- int timeoutSec = 0;
- if (nlAttr != null) {
- timeoutSec = nlAttr.getValueAsBe32(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_ORIG), byteBuffer);
- Tuple tupleOrig = null;
- if (nlAttr != null) {
- tupleOrig = parseTuple(nlAttr.getValueAsByteBuffer());
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_REPLY), byteBuffer);
- Tuple tupleReply = null;
- if (nlAttr != null) {
- tupleReply = parseTuple(nlAttr.getValueAsByteBuffer());
- }
-
- // Advance to the end of the message.
- byteBuffer.position(baseOffset);
- final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
- final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
- header.nlmsg_len - kMinConsumed);
- if (byteBuffer.remaining() < kAdditionalSpace) {
- return null;
- }
- byteBuffer.position(baseOffset + kAdditionalSpace);
-
- return new ConntrackMessage(header, nfGenMsg, tupleOrig, tupleReply, status, timeoutSec);
- }
-
- /**
- * Parses a conntrack tuple from a {@link ByteBuffer}.
- *
- * The attribute parsing is interesting on:
- * - CTA_TUPLE_IP
- * CTA_IP_V4_SRC
- * CTA_IP_V4_DST
- * - CTA_TUPLE_PROTO
- * CTA_PROTO_NUM
- * CTA_PROTO_SRC_PORT
- * CTA_PROTO_DST_PORT
- *
- * Assume that the minimum size is the sum of CTA_TUPLE_IP (size: 20) and CTA_TUPLE_PROTO
- * (size: 28). Here is an example for an expected CTA_TUPLE_ORIG message in raw data:
- * +--------------------------------------------------------------------------------------+
- * | CTA_TUPLE_ORIG |
- * +--------------------------+-----------------------------------------------------------+
- * | 1400 | nla_len = 20 |
- * | 0180 | nla_type = nested CTA_TUPLE_IP |
- * | 0800 0100 C0A8500C | nla_type=CTA_IP_V4_SRC, ip=192.168.80.12 |
- * | 0800 0200 8C700874 | nla_type=CTA_IP_V4_DST, ip=140.112.8.116 |
- * | 1C00 | nla_len = 28 |
- * | 0280 | nla_type = nested CTA_TUPLE_PROTO |
- * | 0500 0100 06 000000 | nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6) |
- * | 0600 0200 F3F1 0000 | nla_type=CTA_PROTO_SRC_PORT, port=62449 (big endian) |
- * | 0600 0300 01BB 0000 | nla_type=CTA_PROTO_DST_PORT, port=433 (big endian) |
- * +--------------------------+-----------------------------------------------------------+
- *
- * The position of the byte buffer doesn't set to the end when the function returns. It is okay
- * because the caller ConntrackMessage#parse has passed a copy which is used for this parser
- * only. Moreover, the parser behavior is the same as other existing netlink struct class
- * parser. Ex: StructInetDiagMsg#parse.
- */
- @Nullable
- private static Tuple parseTuple(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- TupleIpv4 tupleIpv4 = null;
- TupleProto tupleProto = null;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_IP), byteBuffer);
- if (nlAttr != null) {
- tupleIpv4 = parseTupleIpv4(nlAttr.getValueAsByteBuffer());
- }
- if (tupleIpv4 == null) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(makeNestedType(CTA_TUPLE_PROTO), byteBuffer);
- if (nlAttr != null) {
- tupleProto = parseTupleProto(nlAttr.getValueAsByteBuffer());
- }
- if (tupleProto == null) return null;
-
- return new Tuple(tupleIpv4, tupleProto);
- }
-
- @Nullable
- private static Inet4Address castToInet4Address(@Nullable InetAddress address) {
- if (address == null || !(address instanceof Inet4Address)) return null;
- return (Inet4Address) address;
- }
-
- @Nullable
- private static TupleIpv4 parseTupleIpv4(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- Inet4Address src = null;
- Inet4Address dst = null;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_IP_V4_SRC, byteBuffer);
- if (nlAttr != null) {
- src = castToInet4Address(nlAttr.getValueAsInetAddress());
- }
- if (src == null) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = findNextAttrOfType(CTA_IP_V4_DST, byteBuffer);
- if (nlAttr != null) {
- dst = castToInet4Address(nlAttr.getValueAsInetAddress());
- }
- if (dst == null) return null;
-
- return new TupleIpv4(src, dst);
- }
-
- @Nullable
- private static TupleProto parseTupleProto(@Nullable ByteBuffer byteBuffer) {
- if (byteBuffer == null) return null;
-
- byte protoNum = 0;
- short srcPort = 0;
- short dstPort = 0;
-
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = findNextAttrOfType(CTA_PROTO_NUM, byteBuffer);
- if (nlAttr != null) {
- protoNum = nlAttr.getValueAsByte((byte) 0);
- }
- if (!(protoNum == IPPROTO_TCP || protoNum == IPPROTO_UDP)) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(CTA_PROTO_SRC_PORT, byteBuffer);
- if (nlAttr != null) {
- srcPort = nlAttr.getValueAsBe16((short) 0);
- }
- if (srcPort == 0) return null;
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(CTA_PROTO_DST_PORT, byteBuffer);
- if (nlAttr != null) {
- dstPort = nlAttr.getValueAsBe16((short) 0);
- }
- if (dstPort == 0) return null;
-
- return new TupleProto(protoNum, srcPort, dstPort);
- }
-
- /**
- * Netfilter header.
- */
- public final StructNfGenMsg nfGenMsg;
- /**
- * Original direction conntrack tuple.
- *
- * The tuple is determined by the parsed attribute value CTA_TUPLE_ORIG, or null if the
- * tuple could not be parsed successfully (for example, if it was truncated or absent).
- */
- @Nullable
- public final Tuple tupleOrig;
- /**
- * Reply direction conntrack tuple.
- *
- * The tuple is determined by the parsed attribute value CTA_TUPLE_REPLY, or null if the
- * tuple could not be parsed successfully (for example, if it was truncated or absent).
- */
- @Nullable
- public final Tuple tupleReply;
- /**
- * Connection status. A bitmask of ip_conntrack_status enum flags.
- *
- * The status is determined by the parsed attribute value CTA_STATUS, or 0 if the status could
- * not be parsed successfully (for example, if it was truncated or absent). For the message
- * from kernel, the valid status is non-zero. For the message from user space, the status may
- * be 0 (absent).
- */
- public final int status;
- /**
- * Conntrack timeout.
- *
- * The timeout is determined by the parsed attribute value CTA_TIMEOUT, or 0 if the timeout
- * could not be parsed successfully (for example, if it was truncated or absent). For
- * IPCTNL_MSG_CT_NEW event, the valid timeout is non-zero. For IPCTNL_MSG_CT_DELETE event, the
- * timeout is 0 (absent).
- */
- public final int timeoutSec;
-
- private ConntrackMessage() {
- super(new StructNlMsgHdr());
- nfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
-
- // This constructor is only used by #newIPv4TimeoutUpdateRequest which doesn't use these
- // data member for packing message. Simply fill them to null or 0.
- tupleOrig = null;
- tupleReply = null;
- status = 0;
- timeoutSec = 0;
- }
-
- private ConntrackMessage(@NonNull StructNlMsgHdr header, @NonNull StructNfGenMsg nfGenMsg,
- @Nullable Tuple tupleOrig, @Nullable Tuple tupleReply, int status, int timeoutSec) {
- super(header);
- this.nfGenMsg = nfGenMsg;
- this.tupleOrig = tupleOrig;
- this.tupleReply = tupleReply;
- this.status = status;
- this.timeoutSec = timeoutSec;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- mHeader.pack(byteBuffer);
- nfGenMsg.pack(byteBuffer);
- }
-
- public short getMessageType() {
- return (short) (getHeader().nlmsg_type & ~(NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8));
- }
-
- /**
- * Convert an ip conntrack status to a string.
- */
- public static String stringForIpConntrackStatus(int flags) {
- final StringBuilder sb = new StringBuilder();
-
- if ((flags & IPS_EXPECTED) != 0) {
- sb.append("IPS_EXPECTED");
- }
- if ((flags & IPS_SEEN_REPLY) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SEEN_REPLY");
- }
- if ((flags & IPS_ASSURED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_ASSURED");
- }
- if ((flags & IPS_CONFIRMED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_CONFIRMED");
- }
- if ((flags & IPS_SRC_NAT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SRC_NAT");
- }
- if ((flags & IPS_DST_NAT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DST_NAT");
- }
- if ((flags & IPS_SEQ_ADJUST) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SEQ_ADJUST");
- }
- if ((flags & IPS_SRC_NAT_DONE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_SRC_NAT_DONE");
- }
- if ((flags & IPS_DST_NAT_DONE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DST_NAT_DONE");
- }
- if ((flags & IPS_DYING) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_DYING");
- }
- if ((flags & IPS_FIXED_TIMEOUT) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_FIXED_TIMEOUT");
- }
- if ((flags & IPS_TEMPLATE) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_TEMPLATE");
- }
- if ((flags & IPS_UNTRACKED) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_UNTRACKED");
- }
- if ((flags & IPS_HELPER) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_HELPER");
- }
- if ((flags & IPS_OFFLOAD) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_OFFLOAD");
- }
- if ((flags & IPS_HW_OFFLOAD) != 0) {
- if (sb.length() > 0) sb.append("|");
- sb.append("IPS_HW_OFFLOAD");
- }
- return sb.toString();
- }
-
- @Override
- public String toString() {
- return "ConntrackMessage{"
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(OsConstants.NETLINK_NETFILTER))
- + "}, "
- + "nfgenmsg{" + nfGenMsg + "}, "
- + "tuple_orig{" + tupleOrig + "}, "
- + "tuple_reply{" + tupleReply + "}, "
- + "status{" + status + "(" + stringForIpConntrackStatus(status) + ")" + "}, "
- + "timeout_sec{" + Integer.toUnsignedLong(timeoutSec) + "}"
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/InetDiagMessage.java b/common/netlinkclient/src/android/net/netlink/InetDiagMessage.java
deleted file mode 100644
index c085123..0000000
--- a/common/netlinkclient/src/android/net/netlink/InetDiagMessage.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2018 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.netlink;
-
-import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.os.Process.INVALID_UID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-
-import android.annotation.Nullable;
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetSocketAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for netlink inet_diag messages.
- *
- * see also: <linux_src>/include/uapi/linux/inet_diag.h
- *
- * @hide
- */
-public class InetDiagMessage extends NetlinkMessage {
- public static final String TAG = "InetDiagMessage";
- private static final int TIMEOUT_MS = 500;
-
- public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags) {
- return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
- 0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
- }
-
- /**
- * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
- * if local and remote are not both null or both non-null.
- *
- * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
- * IPPROTO_UDP, or IPPROTO_UDPLITE.
- * @param local local socket address of the target socket. This will be packed into a
- * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param remote remote socket address of the target socket. This will be packed into a
- * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
- * local or remote address is null.
- * @param family the ip family of the request message. This should be set to either AF_INET or
- * AF_INET6 for IPv4 or IPv6 sockets respectively.
- * @param flags message flags. See <linux_src>/include/uapi/linux/netlink.h.
- * @param pad for raw socket protocol specification.
- * @param idiagExt a set of flags defining what kind of extended information to report.
- * @param state a bit mask that defines a filter of socket states.
- *
- * @return bytes array representation of the message
- **/
- public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
- @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
- int state) throws NullPointerException {
- final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
- nlMsgHdr.nlmsg_len = bytes.length;
- nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
- nlMsgHdr.nlmsg_flags = flags;
- nlMsgHdr.pack(byteBuffer);
- final StructInetDiagReqV2 inetDiagReqV2 =
- new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
-
- inetDiagReqV2.pack(byteBuffer);
- return bytes;
- }
-
- public StructInetDiagMsg mStructInetDiagMsg;
-
- private InetDiagMessage(StructNlMsgHdr header) {
- super(header);
- mStructInetDiagMsg = new StructInetDiagMsg();
- }
-
- public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final InetDiagMessage msg = new InetDiagMessage(header);
- msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
- return msg;
- }
-
- private static int lookupUidByFamily(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags,
- FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- byte[] msg = InetDiagReqV2(protocol, local, remote, family, flags);
- NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
- ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
-
- final NetlinkMessage nlMsg = NetlinkMessage.parse(response, NETLINK_INET_DIAG);
- final StructNlMsgHdr hdr = nlMsg.getHeader();
- if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
- return INVALID_UID;
- }
- if (nlMsg instanceof InetDiagMessage) {
- return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.idiag_uid;
- }
- return INVALID_UID;
- }
-
- private static final int FAMILY[] = {AF_INET6, AF_INET};
-
- private static int lookupUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote, FileDescriptor fd)
- throws ErrnoException, InterruptedIOException {
- int uid;
-
- for (int family : FAMILY) {
- /**
- * For exact match lookup, swap local and remote for UDP lookups due to kernel
- * bug which will not be fixed. See aosp/755889 and
- * https://www.mail-archive.com/[email protected]/msg248638.html
- */
- if (protocol == IPPROTO_UDP) {
- uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd);
- } else {
- uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd);
- }
- if (uid != INVALID_UID) {
- return uid;
- }
- }
-
- /**
- * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the
- * socket is not connected (and even if the socket is connected to a different destination).
- * If we want this API to work for such packets, then on miss we need to do a second lookup
- * with only the local address and port filled in.
- * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard.
- */
- if (protocol == IPPROTO_UDP) {
- try {
- InetSocketAddress wildcard = new InetSocketAddress(
- Inet6Address.getByName("::"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0);
- uid = lookupUidByFamily(protocol, local, wildcard, AF_INET,
- (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
- if (uid != INVALID_UID) {
- return uid;
- }
- } catch (UnknownHostException e) {
- Log.e(TAG, e.toString());
- }
- }
- return INVALID_UID;
- }
-
- /**
- * Use an inet_diag socket to look up the UID associated with the input local and remote
- * address/port and protocol of a connection.
- */
- public static int getConnectionOwnerUid(int protocol, InetSocketAddress local,
- InetSocketAddress remote) {
- int uid = INVALID_UID;
- FileDescriptor fd = null;
- try {
- fd = NetlinkSocket.forProto(NETLINK_INET_DIAG);
- NetlinkSocket.connectToKernel(fd);
- uid = lookupUid(protocol, local, remote, fd);
- } catch (ErrnoException | SocketException | IllegalArgumentException
- | InterruptedIOException e) {
- Log.e(TAG, e.toString());
- } finally {
- if (fd != null) {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException e) {
- Log.e(TAG, e.toString());
- }
- }
- }
- return uid;
- }
-
- @Override
- public String toString() {
- return "InetDiagMessage{ "
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(NETLINK_INET_DIAG)) + "}, "
- + "inet_diag_msg{"
- + (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NdOption.java b/common/netlinkclient/src/android/net/netlink/NdOption.java
deleted file mode 100644
index ab9d2e6..0000000
--- a/common/netlinkclient/src/android/net/netlink/NdOption.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.netlink;
-
-import java.nio.ByteBuffer;
-
-/**
- * Base class for IPv6 neighbour discovery options.
- */
-public class NdOption {
- public static final int STRUCT_SIZE = 2;
-
- /** The option type. */
- public final byte type;
- /** The length of the option in 8-byte units. Actually an unsigned 8-bit integer */
- public final int length;
-
- /** Constructs a new NdOption. */
- NdOption(byte type, int length) {
- this.type = type;
- this.length = length;
- }
-
- /**
- * Parses a neighbour discovery option.
- *
- * Parses (and consumes) the option if it is of a known type. If the option is of an unknown
- * type, advances the buffer (so the caller can continue parsing if desired) and returns
- * {@link #UNKNOWN}. If the option claims a length of 0, returns null because parsing cannot
- * continue.
- *
- * No checks are performed on the length other than ensuring it is not 0, so if a caller wants
- * to deal with options that might overflow the structure that contains them, it must explicitly
- * set the buffer's limit to the position at which that structure ends.
- *
- * @param buf the buffer to parse.
- * @return a subclass of {@link NdOption}, or {@code null} for an unknown or malformed option.
- */
- public static NdOption parse(ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
-
- // Peek the type without advancing the buffer.
- byte type = buf.get(buf.position());
- int length = Byte.toUnsignedInt(buf.get(buf.position() + 1));
- if (length == 0) return null;
-
- switch (type) {
- case StructNdOptPref64.TYPE:
- return StructNdOptPref64.parse(buf);
-
- default:
- int newPosition = Math.min(buf.limit(), buf.position() + length * 8);
- buf.position(newPosition);
- return UNKNOWN;
- }
- }
-
- void writeToByteBuffer(ByteBuffer buf) {
- buf.put(type);
- buf.put((byte) length);
- }
-
- @Override
- public String toString() {
- return String.format("NdOption(%d, %d)", Byte.toUnsignedInt(type), length);
- }
-
- public static final NdOption UNKNOWN = new NdOption((byte) 0, 0);
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NduseroptMessage.java b/common/netlinkclient/src/android/net/netlink/NduseroptMessage.java
deleted file mode 100644
index 7b976f1..0000000
--- a/common/netlinkclient/src/android/net/netlink/NduseroptMessage.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.netlink;
-
-import static android.system.OsConstants.AF_INET6;
-
-import androidx.annotation.NonNull;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * A NetlinkMessage subclass for RTM_NEWNDUSEROPT messages.
- */
-public class NduseroptMessage extends NetlinkMessage {
- public static final int STRUCT_SIZE = 16;
-
- static final int NDUSEROPT_SRCADDR = 1;
-
- /** The address family. Presumably always AF_INET6. */
- public final byte family;
- /**
- * The total length in bytes of the options that follow this structure.
- * Actually a 16-bit unsigned integer.
- */
- public final int opts_len;
- /** The interface index on which the options were received. */
- public final int ifindex;
- /** The ICMP type of the packet that contained the options. */
- public final byte icmp_type;
- /** The ICMP code of the packet that contained the options. */
- public final byte icmp_code;
-
- /**
- * ND option that was in this message.
- * Even though the length field is called "opts_len", the kernel only ever sends one option per
- * message. It is unlikely that this will ever change as it would break existing userspace code.
- * But if it does, we can simply update this code, since userspace is typically newer than the
- * kernel.
- */
- public final NdOption option;
-
- /** The IP address that sent the packet containing the option. */
- public final InetAddress srcaddr;
-
- NduseroptMessage(@NonNull StructNlMsgHdr header, @NonNull ByteBuffer buf)
- throws UnknownHostException {
- super(header);
-
- // The structure itself.
- buf.order(ByteOrder.nativeOrder()); // Restored in the finally clause inside parse().
- final int start = buf.position();
- family = buf.get();
- buf.get(); // Skip 1 byte of padding.
- opts_len = Short.toUnsignedInt(buf.getShort());
- ifindex = buf.getInt();
- icmp_type = buf.get();
- icmp_code = buf.get();
- buf.position(buf.position() + 6); // Skip 6 bytes of padding.
-
- // The ND option.
- // Ensure we don't read past opts_len even if the option length is invalid.
- // Note that this check is not really necessary since if the option length is not valid,
- // this struct won't be very useful to the caller.
- buf.order(ByteOrder.BIG_ENDIAN);
- int oldLimit = buf.limit();
- buf.limit(start + STRUCT_SIZE + opts_len);
- try {
- option = NdOption.parse(buf);
- } finally {
- buf.limit(oldLimit);
- }
-
- // The source address.
- int newPosition = start + STRUCT_SIZE + opts_len;
- if (newPosition >= buf.limit()) {
- throw new IllegalArgumentException("ND options extend past end of buffer");
- }
- buf.position(newPosition);
-
- StructNlAttr nla = StructNlAttr.parse(buf);
- if (nla == null || nla.nla_type != NDUSEROPT_SRCADDR || nla.nla_value == null) {
- throw new IllegalArgumentException("Invalid source address in ND useropt");
- }
- if (family == AF_INET6) {
- // InetAddress.getByAddress only looks at the ifindex if the address type needs one.
- srcaddr = Inet6Address.getByAddress(null /* hostname */, nla.nla_value, ifindex);
- } else {
- srcaddr = InetAddress.getByAddress(nla.nla_value);
- }
- }
-
- /**
- * Parses a StructNduseroptmsg from a {@link ByteBuffer}.
- *
- * @param header the netlink message header.
- * @param buf The buffer from which to parse the option. The buffer's byte order must be
- * {@link java.nio.ByteOrder#BIG_ENDIAN}.
- * @return the parsed option, or {@code null} if the option could not be parsed successfully
- * (for example, if it was truncated, or if the prefix length code was wrong).
- */
- public static NduseroptMessage parse(@NonNull StructNlMsgHdr header, @NonNull ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
- ByteOrder oldOrder = buf.order();
- try {
- return new NduseroptMessage(header, buf);
- } catch (IllegalArgumentException | UnknownHostException | BufferUnderflowException e) {
- // Not great, but better than throwing an exception that might crash the caller.
- // Convention in this package is that null indicates that the option was truncated, so
- // callers must already handle it.
- return null;
- } finally {
- buf.order(oldOrder);
- }
- }
-
- @Override
- public String toString() {
- return String.format("Nduseroptmsg(%d, %d, %d, %d, %d, %s)",
- family, opts_len, ifindex, Byte.toUnsignedInt(icmp_type),
- Byte.toUnsignedInt(icmp_code), srcaddr.getHostAddress());
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NetlinkConstants.java b/common/netlinkclient/src/android/net/netlink/NetlinkConstants.java
deleted file mode 100644
index b4d9cc0..0000000
--- a/common/netlinkclient/src/android/net/netlink/NetlinkConstants.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2015 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.netlink;
-
-import android.annotation.NonNull;
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * Various constants and static helper methods for netlink communications.
- *
- * Values taken from:
- *
- * include/uapi/linux/netfilter/nfnetlink.h
- * include/uapi/linux/netfilter/nfnetlink_conntrack.h
- * include/uapi/linux/netlink.h
- * include/uapi/linux/rtnetlink.h
- *
- * @hide
- */
-public class NetlinkConstants {
- private NetlinkConstants() {}
-
- public static final int NLA_ALIGNTO = 4;
- /**
- * Flag for dumping struct tcp_info.
- * Corresponding to enum definition in external/strace/linux/inet_diag.h.
- */
- public static final int INET_DIAG_MEMINFO = 1;
-
- public static final int SOCKDIAG_MSG_HEADER_SIZE =
- StructNlMsgHdr.STRUCT_SIZE + StructInetDiagMsg.STRUCT_SIZE;
-
- public static final int alignedLengthOf(short length) {
- final int intLength = (int) length & 0xffff;
- return alignedLengthOf(intLength);
- }
-
- public static final int alignedLengthOf(int length) {
- if (length <= 0) { return 0; }
- return (((length + NLA_ALIGNTO - 1) / NLA_ALIGNTO) * NLA_ALIGNTO);
- }
-
- public static String stringForAddressFamily(int family) {
- if (family == OsConstants.AF_INET) { return "AF_INET"; }
- if (family == OsConstants.AF_INET6) { return "AF_INET6"; }
- if (family == OsConstants.AF_NETLINK) { return "AF_NETLINK"; }
- return String.valueOf(family);
- }
-
- public static String stringForProtocol(int protocol) {
- if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; }
- if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; }
- return String.valueOf(protocol);
- }
-
- public static String hexify(byte[] bytes) {
- if (bytes == null) { return "(null)"; }
- return toHexString(bytes, 0, bytes.length);
- }
-
- public static String hexify(ByteBuffer buffer) {
- if (buffer == null) { return "(null)"; }
- return toHexString(
- buffer.array(), buffer.position(), buffer.remaining());
- }
-
- // Known values for struct nlmsghdr nlm_type.
- public static final short NLMSG_NOOP = 1; // Nothing
- public static final short NLMSG_ERROR = 2; // Error
- public static final short NLMSG_DONE = 3; // End of a dump
- public static final short NLMSG_OVERRUN = 4; // Data lost
- public static final short NLMSG_MAX_RESERVED = 15; // Max reserved value
-
- public static final short RTM_NEWLINK = 16;
- public static final short RTM_DELLINK = 17;
- public static final short RTM_GETLINK = 18;
- public static final short RTM_SETLINK = 19;
- public static final short RTM_NEWADDR = 20;
- public static final short RTM_DELADDR = 21;
- public static final short RTM_GETADDR = 22;
- public static final short RTM_NEWROUTE = 24;
- public static final short RTM_DELROUTE = 25;
- public static final short RTM_GETROUTE = 26;
- public static final short RTM_NEWNEIGH = 28;
- public static final short RTM_DELNEIGH = 29;
- public static final short RTM_GETNEIGH = 30;
- public static final short RTM_NEWRULE = 32;
- public static final short RTM_DELRULE = 33;
- public static final short RTM_GETRULE = 34;
- public static final short RTM_NEWNDUSEROPT = 68;
-
- // Netfilter netlink message types are presented by two bytes: high byte subsystem and
- // low byte operation. See the macro NFNL_SUBSYS_ID and NFNL_MSG_TYPE in
- // include/uapi/linux/netfilter/nfnetlink.h
- public static final short NFNL_SUBSYS_CTNETLINK = 1;
-
- public static final short IPCTNL_MSG_CT_NEW = 0;
- public static final short IPCTNL_MSG_CT_GET = 1;
- public static final short IPCTNL_MSG_CT_DELETE = 2;
- public static final short IPCTNL_MSG_CT_GET_CTRZERO = 3;
- public static final short IPCTNL_MSG_CT_GET_STATS_CPU = 4;
- public static final short IPCTNL_MSG_CT_GET_STATS = 5;
- public static final short IPCTNL_MSG_CT_GET_DYING = 6;
- public static final short IPCTNL_MSG_CT_GET_UNCONFIRMED = 7;
-
- /* see include/uapi/linux/sock_diag.h */
- public static final short SOCK_DIAG_BY_FAMILY = 20;
-
- // Netlink groups.
- public static final int RTNLGRP_ND_USEROPT = 20;
- public static final int RTMGRP_ND_USEROPT = 1 << (RTNLGRP_ND_USEROPT - 1);
-
- /**
- * Convert a netlink message type to a string for control message.
- */
- @NonNull
- private static String stringForCtlMsgType(short nlmType) {
- switch (nlmType) {
- case NLMSG_NOOP: return "NLMSG_NOOP";
- case NLMSG_ERROR: return "NLMSG_ERROR";
- case NLMSG_DONE: return "NLMSG_DONE";
- case NLMSG_OVERRUN: return "NLMSG_OVERRUN";
- default: return "unknown control message type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_ROUTE.
- */
- @NonNull
- private static String stringForRtMsgType(short nlmType) {
- switch (nlmType) {
- case RTM_NEWLINK: return "RTM_NEWLINK";
- case RTM_DELLINK: return "RTM_DELLINK";
- case RTM_GETLINK: return "RTM_GETLINK";
- case RTM_SETLINK: return "RTM_SETLINK";
- case RTM_NEWADDR: return "RTM_NEWADDR";
- case RTM_DELADDR: return "RTM_DELADDR";
- case RTM_GETADDR: return "RTM_GETADDR";
- case RTM_NEWROUTE: return "RTM_NEWROUTE";
- case RTM_DELROUTE: return "RTM_DELROUTE";
- case RTM_GETROUTE: return "RTM_GETROUTE";
- case RTM_NEWNEIGH: return "RTM_NEWNEIGH";
- case RTM_DELNEIGH: return "RTM_DELNEIGH";
- case RTM_GETNEIGH: return "RTM_GETNEIGH";
- case RTM_NEWRULE: return "RTM_NEWRULE";
- case RTM_DELRULE: return "RTM_DELRULE";
- case RTM_GETRULE: return "RTM_GETRULE";
- case RTM_NEWNDUSEROPT: return "RTM_NEWNDUSEROPT";
- default: return "unknown RTM type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_INET_DIAG.
- */
- @NonNull
- private static String stringForInetDiagMsgType(short nlmType) {
- switch (nlmType) {
- case SOCK_DIAG_BY_FAMILY: return "SOCK_DIAG_BY_FAMILY";
- default: return "unknown SOCK_DIAG type: " + String.valueOf(nlmType);
- }
- }
-
- /**
- * Convert a netlink message type to a string for NETLINK_NETFILTER.
- */
- @NonNull
- private static String stringForNfMsgType(short nlmType) {
- final byte subsysId = (byte) (nlmType >> 8);
- final byte msgType = (byte) nlmType;
- switch (subsysId) {
- case NFNL_SUBSYS_CTNETLINK:
- switch (msgType) {
- case IPCTNL_MSG_CT_NEW: return "IPCTNL_MSG_CT_NEW";
- case IPCTNL_MSG_CT_GET: return "IPCTNL_MSG_CT_GET";
- case IPCTNL_MSG_CT_DELETE: return "IPCTNL_MSG_CT_DELETE";
- case IPCTNL_MSG_CT_GET_CTRZERO: return "IPCTNL_MSG_CT_GET_CTRZERO";
- case IPCTNL_MSG_CT_GET_STATS_CPU: return "IPCTNL_MSG_CT_GET_STATS_CPU";
- case IPCTNL_MSG_CT_GET_STATS: return "IPCTNL_MSG_CT_GET_STATS";
- case IPCTNL_MSG_CT_GET_DYING: return "IPCTNL_MSG_CT_GET_DYING";
- case IPCTNL_MSG_CT_GET_UNCONFIRMED: return "IPCTNL_MSG_CT_GET_UNCONFIRMED";
- }
- break;
- }
- return "unknown NETFILTER type: " + String.valueOf(nlmType);
- }
-
- /**
- * Convert a netlink message type to a string by netlink family.
- */
- @NonNull
- public static String stringForNlMsgType(short nlmType, int nlFamily) {
- // Reserved control messages. The netlink family is ignored.
- // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
- if (nlmType <= NLMSG_MAX_RESERVED) return stringForCtlMsgType(nlmType);
-
- // Netlink family messages. The netlink family is required. Note that the reason for using
- // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
- // not constant.
- if (nlFamily == OsConstants.NETLINK_ROUTE) return stringForRtMsgType(nlmType);
- if (nlFamily == OsConstants.NETLINK_INET_DIAG) return stringForInetDiagMsgType(nlmType);
- if (nlFamily == OsConstants.NETLINK_NETFILTER) return stringForNfMsgType(nlmType);
-
- return "unknown type: " + String.valueOf(nlmType);
- }
-
- private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F' };
- /**
- * Convert a byte array to a hexadecimal string.
- */
- public static String toHexString(byte[] array, int offset, int length) {
- char[] buf = new char[length * 2];
-
- int bufIndex = 0;
- for (int i = offset; i < offset + length; i++) {
- byte b = array[i];
- buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
- buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
- }
-
- return new String(buf);
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NetlinkErrorMessage.java b/common/netlinkclient/src/android/net/netlink/NetlinkErrorMessage.java
deleted file mode 100644
index 36b02c6..0000000
--- a/common/netlinkclient/src/android/net/netlink/NetlinkErrorMessage.java
+++ /dev/null
@@ -1,58 +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.netlink;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * A NetlinkMessage subclass for netlink error messages.
- *
- * @hide
- */
-public class NetlinkErrorMessage extends NetlinkMessage {
-
- public static NetlinkErrorMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final NetlinkErrorMessage errorMsg = new NetlinkErrorMessage(header);
-
- errorMsg.mNlMsgErr = StructNlMsgErr.parse(byteBuffer);
- if (errorMsg.mNlMsgErr == null) {
- return null;
- }
-
- return errorMsg;
- }
-
- private StructNlMsgErr mNlMsgErr;
-
- NetlinkErrorMessage(StructNlMsgHdr header) {
- super(header);
- mNlMsgErr = null;
- }
-
- public StructNlMsgErr getNlMsgError() {
- return mNlMsgErr;
- }
-
- @Override
- public String toString() {
- return "NetlinkErrorMessage{ "
- + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
- + "nlmsgerr{" + (mNlMsgErr == null ? "" : mNlMsgErr.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NetlinkMessage.java b/common/netlinkclient/src/android/net/netlink/NetlinkMessage.java
deleted file mode 100644
index ab2c223..0000000
--- a/common/netlinkclient/src/android/net/netlink/NetlinkMessage.java
+++ /dev/null
@@ -1,153 +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.netlink;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * NetlinkMessage base class for other, more specific netlink message types.
- *
- * Classes that extend NetlinkMessage should:
- * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method
- * - returning either null (parse errors) or a new object of the subclass
- * type (cast-able to NetlinkMessage)
- *
- * NetlinkMessage.parse() should be updated to know which nlmsg_type values
- * correspond with which message subclasses.
- *
- * @hide
- */
-public class NetlinkMessage {
- private final static String TAG = "NetlinkMessage";
-
- /**
- * Parsing netlink messages for reserved control message or specific netlink message. The
- * netlink family is required for parsing specific netlink message. See man-pages/netlink.
- */
- @Nullable
- public static NetlinkMessage parse(@NonNull ByteBuffer byteBuffer, int nlFamily) {
- final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
- final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
- if (nlmsghdr == null) {
- return null;
- }
-
- int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
- payloadLength -= StructNlMsgHdr.STRUCT_SIZE;
- if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) {
- // Malformed message or runt buffer. Pretend the buffer was consumed.
- byteBuffer.position(byteBuffer.limit());
- return null;
- }
-
- // Reserved control messages. The netlink family is ignored.
- // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h.
- if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
- return parseCtlMessage(nlmsghdr, byteBuffer, payloadLength);
- }
-
- // Netlink family messages. The netlink family is required. Note that the reason for using
- // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are
- // not constant.
- if (nlFamily == OsConstants.NETLINK_ROUTE) {
- return parseRtMessage(nlmsghdr, byteBuffer);
- } else if (nlFamily == OsConstants.NETLINK_INET_DIAG) {
- return parseInetDiagMessage(nlmsghdr, byteBuffer);
- } else if (nlFamily == OsConstants.NETLINK_NETFILTER) {
- return parseNfMessage(nlmsghdr, byteBuffer);
- }
-
- return null;
- }
-
- protected StructNlMsgHdr mHeader;
-
- public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
- mHeader = nlmsghdr;
- }
-
- public StructNlMsgHdr getHeader() {
- return mHeader;
- }
-
- @Override
- public String toString() {
- // The netlink family is not provided to StructNlMsgHdr#toString because NetlinkMessage
- // doesn't store the information. So the netlink message type can't be transformed into
- // a string by StructNlMsgHdr#toString and just keep as an integer. The specific message
- // which inherits NetlinkMessage could override NetlinkMessage#toString and provide the
- // specific netlink family to StructNlMsgHdr#toString.
- return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
- }
-
- @NonNull
- private static NetlinkMessage parseCtlMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer, int payloadLength) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.NLMSG_ERROR:
- return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
- default: {
- // Other netlink control messages. Just parse the header for now,
- // pretending the whole message was consumed.
- byteBuffer.position(byteBuffer.position() + payloadLength);
- return new NetlinkMessage(nlmsghdr);
- }
- }
- }
-
- @Nullable
- private static NetlinkMessage parseRtMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.RTM_NEWNEIGH:
- case NetlinkConstants.RTM_DELNEIGH:
- case NetlinkConstants.RTM_GETNEIGH:
- return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
- case NetlinkConstants.RTM_NEWNDUSEROPT:
- return (NetlinkMessage) NduseroptMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-
- @Nullable
- private static NetlinkMessage parseInetDiagMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
- return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-
- @Nullable
- private static NetlinkMessage parseNfMessage(@NonNull StructNlMsgHdr nlmsghdr,
- @NonNull ByteBuffer byteBuffer) {
- switch (nlmsghdr.nlmsg_type) {
- case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
- | NetlinkConstants.IPCTNL_MSG_CT_NEW:
- case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8
- | NetlinkConstants.IPCTNL_MSG_CT_DELETE:
- return (NetlinkMessage) ConntrackMessage.parse(nlmsghdr, byteBuffer);
- default: return null;
- }
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/NetlinkSocket.java b/common/netlinkclient/src/android/net/netlink/NetlinkSocket.java
deleted file mode 100644
index ab4c052..0000000
--- a/common/netlinkclient/src/android/net/netlink/NetlinkSocket.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2015 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.netlink;
-
-import static android.net.util.SocketUtils.makeNetlinkSocketAddress;
-import static android.system.OsConstants.AF_NETLINK;
-import static android.system.OsConstants.EIO;
-import static android.system.OsConstants.EPROTO;
-import static android.system.OsConstants.ETIMEDOUT;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOL_SOCKET;
-import static android.system.OsConstants.SO_RCVBUF;
-import static android.system.OsConstants.SO_RCVTIMEO;
-import static android.system.OsConstants.SO_SNDTIMEO;
-
-import android.net.util.SocketUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.StructTimeval;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * NetlinkSocket
- *
- * A small static class to assist with AF_NETLINK socket operations.
- *
- * @hide
- */
-public class NetlinkSocket {
- private static final String TAG = "NetlinkSocket";
-
- public static final int DEFAULT_RECV_BUFSIZE = 8 * 1024;
- public static final int SOCKET_RECV_BUFSIZE = 64 * 1024;
-
- public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
- final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
- final long IO_TIMEOUT = 300L;
-
- final FileDescriptor fd = forProto(nlProto);
-
- try {
- connectToKernel(fd);
- sendMessage(fd, msg, 0, msg.length, IO_TIMEOUT);
- final ByteBuffer bytes = recvMessage(fd, DEFAULT_RECV_BUFSIZE, IO_TIMEOUT);
- // recvMessage() guaranteed to not return null if it did not throw.
- final NetlinkMessage response = NetlinkMessage.parse(bytes, nlProto);
- if (response != null && response instanceof NetlinkErrorMessage &&
- (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
- final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
- if (errno != 0) {
- // TODO: consider ignoring EINVAL (-22), which appears to be
- // normal when probing a neighbor for which the kernel does
- // not already have / no longer has a link layer address.
- Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
- // Note: convert kernel errnos (negative) into userspace errnos (positive).
- throw new ErrnoException(response.toString(), Math.abs(errno));
- }
- } else {
- final String errmsg;
- if (response == null) {
- bytes.position(0);
- errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
- } else {
- errmsg = response.toString();
- }
- Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
- throw new ErrnoException(errmsg, EPROTO);
- }
- } catch (InterruptedIOException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, ETIMEDOUT, e);
- } catch (SocketException e) {
- Log.e(TAG, errPrefix, e);
- throw new ErrnoException(errPrefix, EIO, e);
- } finally {
- try {
- SocketUtils.closeSocket(fd);
- } catch (IOException e) {
- // Nothing we can do here
- }
- }
- }
-
- public static FileDescriptor forProto(int nlProto) throws ErrnoException {
- final FileDescriptor fd = Os.socket(AF_NETLINK, SOCK_DGRAM, nlProto);
- Os.setsockoptInt(fd, SOL_SOCKET, SO_RCVBUF, SOCKET_RECV_BUFSIZE);
- return fd;
- }
-
- public static void connectToKernel(FileDescriptor fd) throws ErrnoException, SocketException {
- Os.connect(fd, makeNetlinkSocketAddress(0, 0));
- }
-
- private static void checkTimeout(long timeoutMs) {
- if (timeoutMs < 0) {
- throw new IllegalArgumentException("Negative timeouts not permitted");
- }
- }
-
- /**
- * Wait up to |timeoutMs| (or until underlying socket error) for a
- * netlink message of at most |bufsize| size.
- *
- * Multi-threaded calls with different timeouts will cause unexpected results.
- */
- public static ByteBuffer recvMessage(FileDescriptor fd, int bufsize, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
-
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(timeoutMs));
-
- ByteBuffer byteBuffer = ByteBuffer.allocate(bufsize);
- int length = Os.read(fd, byteBuffer);
- if (length == bufsize) {
- Log.w(TAG, "maximum read");
- }
- byteBuffer.position(0);
- byteBuffer.limit(length);
- byteBuffer.order(ByteOrder.nativeOrder());
- return byteBuffer;
- }
-
- /**
- * Send a message to a peer to which this socket has previously connected,
- * waiting at most |timeoutMs| milliseconds for the send to complete.
- *
- * Multi-threaded calls with different timeouts will cause unexpected results.
- */
- public static int sendMessage(
- FileDescriptor fd, byte[] bytes, int offset, int count, long timeoutMs)
- throws ErrnoException, IllegalArgumentException, InterruptedIOException {
- checkTimeout(timeoutMs);
- Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(timeoutMs));
- return Os.write(fd, bytes, offset, count);
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/RtNetlinkNeighborMessage.java b/common/netlinkclient/src/android/net/netlink/RtNetlinkNeighborMessage.java
deleted file mode 100644
index 099ff07..0000000
--- a/common/netlinkclient/src/android/net/netlink/RtNetlinkNeighborMessage.java
+++ /dev/null
@@ -1,229 +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.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-
-import android.system.OsConstants;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * A NetlinkMessage subclass for rtnetlink neighbor messages.
- *
- * see also: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class RtNetlinkNeighborMessage extends NetlinkMessage {
- public static final short NDA_UNSPEC = 0;
- public static final short NDA_DST = 1;
- public static final short NDA_LLADDR = 2;
- public static final short NDA_CACHEINFO = 3;
- public static final short NDA_PROBES = 4;
- public static final short NDA_VLAN = 5;
- public static final short NDA_PORT = 6;
- public static final short NDA_VNI = 7;
- public static final short NDA_IFINDEX = 8;
- public static final short NDA_MASTER = 9;
-
- public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
- final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header);
-
- neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer);
- if (neighMsg.mNdmsg == null) {
- return null;
- }
-
- // Some of these are message-type dependent, and not always present.
- final int baseOffset = byteBuffer.position();
- StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(NDA_DST, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mDestination = nlAttr.getValueAsInetAddress();
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_LLADDR, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mLinkLayerAddr = nlAttr.nla_value;
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_PROBES, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mNumProbes = nlAttr.getValueAsInt(0);
- }
-
- byteBuffer.position(baseOffset);
- nlAttr = StructNlAttr.findNextAttrOfType(NDA_CACHEINFO, byteBuffer);
- if (nlAttr != null) {
- neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer());
- }
-
- final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final int kAdditionalSpace = NetlinkConstants.alignedLengthOf(
- neighMsg.mHeader.nlmsg_len - kMinConsumed);
- if (byteBuffer.remaining() < kAdditionalSpace) {
- byteBuffer.position(byteBuffer.limit());
- } else {
- byteBuffer.position(baseOffset + kAdditionalSpace);
- }
-
- return neighMsg;
- }
-
- /**
- * A convenience method to create an RTM_GETNEIGH request message.
- */
- public static byte[] newGetNeighborsRequest(int seqNo) {
- final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- final byte[] bytes = new byte[length];
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_len = length;
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- nlmsghdr.nlmsg_seq = seqNo;
- nlmsghdr.pack(byteBuffer);
-
- final StructNdMsg ndmsg = new StructNdMsg();
- ndmsg.pack(byteBuffer);
-
- return bytes;
- }
-
- /**
- * A convenience method to create an RTM_NEWNEIGH message, to modify
- * the kernel's state information for a specific neighbor.
- */
- public static byte[] newNewNeighborMessage(
- int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) {
- final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
- nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH;
- nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
- nlmsghdr.nlmsg_seq = seqNo;
-
- final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr);
- msg.mNdmsg = new StructNdMsg();
- msg.mNdmsg.ndm_family =
- (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
- msg.mNdmsg.ndm_ifindex = ifIndex;
- msg.mNdmsg.ndm_state = nudState;
- msg.mDestination = ip;
- msg.mLinkLayerAddr = llAddr; // might be null
-
- final byte[] bytes = new byte[msg.getRequiredSpace()];
- nlmsghdr.nlmsg_len = bytes.length;
- final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
- byteBuffer.order(ByteOrder.nativeOrder());
- msg.pack(byteBuffer);
- return bytes;
- }
-
- private StructNdMsg mNdmsg;
- private InetAddress mDestination;
- private byte[] mLinkLayerAddr;
- private int mNumProbes;
- private StructNdaCacheInfo mCacheInfo;
-
- private RtNetlinkNeighborMessage(StructNlMsgHdr header) {
- super(header);
- mNdmsg = null;
- mDestination = null;
- mLinkLayerAddr = null;
- mNumProbes = 0;
- mCacheInfo = null;
- }
-
- public StructNdMsg getNdHeader() {
- return mNdmsg;
- }
-
- public InetAddress getDestination() {
- return mDestination;
- }
-
- public byte[] getLinkLayerAddress() {
- return mLinkLayerAddr;
- }
-
- public int getProbes() {
- return mNumProbes;
- }
-
- public StructNdaCacheInfo getCacheInfo() {
- return mCacheInfo;
- }
-
- public int getRequiredSpace() {
- int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE;
- if (mDestination != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length);
- }
- if (mLinkLayerAddr != null) {
- spaceRequired += NetlinkConstants.alignedLengthOf(
- StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length);
- }
- // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO
- // attributes appended. Fix later, if necessary.
- return spaceRequired;
- }
-
- private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) {
- final StructNlAttr nlAttr = new StructNlAttr();
- nlAttr.nla_type = nlType;
- nlAttr.nla_value = nlValue;
- nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length);
- nlAttr.pack(byteBuffer);
- }
-
- public void pack(ByteBuffer byteBuffer) {
- getHeader().pack(byteBuffer) ;
- mNdmsg.pack(byteBuffer);
-
- if (mDestination != null) {
- packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer);
- }
- if (mLinkLayerAddr != null) {
- packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress();
- return "RtNetlinkNeighborMessage{ "
- + "nlmsghdr{"
- + (mHeader == null ? "" : mHeader.toString(OsConstants.NETLINK_ROUTE)) + "}, "
- + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, "
- + "destination{" + ipLiteral + "} "
- + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} "
- + "probes{" + mNumProbes + "} "
- + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructInetDiagMsg.java b/common/netlinkclient/src/android/net/netlink/StructInetDiagMsg.java
deleted file mode 100644
index 5772a94..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructInetDiagMsg.java
+++ /dev/null
@@ -1,59 +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.netlink;
-
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_msg
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_msg {
- * __u8 idiag_family;
- * __u8 idiag_state;
- * __u8 idiag_timer;
- * __u8 idiag_retrans;
- * struct inet_diag_sockid id;
- * __u32 idiag_expires;
- * __u32 idiag_rqueue;
- * __u32 idiag_wqueue;
- * __u32 idiag_uid;
- * __u32 idiag_inode;
- * };
- *
- * @hide
- */
-public class StructInetDiagMsg {
- public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
- private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 +
- StructInetDiagSockId.STRUCT_SIZE + 12;
- public int idiag_uid;
-
- public static StructInetDiagMsg parse(ByteBuffer byteBuffer) {
- StructInetDiagMsg struct = new StructInetDiagMsg();
- struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET);
- return struct;
- }
-
- @Override
- public String toString() {
- return "StructInetDiagMsg{ "
- + "idiag_uid{" + idiag_uid + "}, "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructInetDiagReqV2.java b/common/netlinkclient/src/android/net/netlink/StructInetDiagReqV2.java
deleted file mode 100644
index 520f0ef..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructInetDiagReqV2.java
+++ /dev/null
@@ -1,97 +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.netlink;
-
-import android.annotation.Nullable;
-
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-
-/**
- * struct inet_diag_req_v2
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_req_v2 {
- * __u8 sdiag_family;
- * __u8 sdiag_protocol;
- * __u8 idiag_ext;
- * __u8 pad;
- * __u32 idiag_states;
- * struct inet_diag_sockid id;
- * };
- *
- * @hide
- */
-public class StructInetDiagReqV2 {
- public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
-
- private final byte mSdiagFamily;
- private final byte mSdiagProtocol;
- private final byte mIdiagExt;
- private final byte mPad;
- private final StructInetDiagSockId mId;
- private final int mState;
- public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
- public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
- int family) {
- this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
- INET_DIAG_REQ_V2_ALL_STATES);
- }
-
- public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
- @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
- throws NullPointerException {
- mSdiagFamily = (byte) family;
- mSdiagProtocol = (byte) protocol;
- // Request for all sockets if no specific socket is requested. Specify the local and remote
- // socket address information for target request socket.
- if ((local == null) != (remote == null)) {
- throw new NullPointerException("Local and remote must be both null or both non-null");
- }
- mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
- mPad = (byte) pad;
- mIdiagExt = (byte) extension;
- mState = state;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller.
- byteBuffer.put((byte) mSdiagFamily);
- byteBuffer.put((byte) mSdiagProtocol);
- byteBuffer.put((byte) mIdiagExt);
- byteBuffer.put((byte) mPad);
- byteBuffer.putInt(mState);
- if (mId != null) mId.pack(byteBuffer);
- }
-
- @Override
- public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
- final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
-
- return "StructInetDiagReqV2{ "
- + "sdiag_family{" + familyStr + "}, "
- + "sdiag_protocol{" + protocolStr + "}, "
- + "idiag_ext{" + mIdiagExt + ")}, "
- + "pad{" + mPad + "}, "
- + "idiag_states{" + Integer.toHexString(mState) + "}, "
- + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructInetDiagSockId.java b/common/netlinkclient/src/android/net/netlink/StructInetDiagSockId.java
deleted file mode 100644
index 2e9fa25..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructInetDiagSockId.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 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.netlink;
-
-import static java.nio.ByteOrder.BIG_ENDIAN;
-
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * struct inet_diag_req_v2
- *
- * see <linux_src>/include/uapi/linux/inet_diag.h
- *
- * struct inet_diag_sockid {
- * __be16 idiag_sport;
- * __be16 idiag_dport;
- * __be32 idiag_src[4];
- * __be32 idiag_dst[4];
- * __u32 idiag_if;
- * __u32 idiag_cookie[2];
- * #define INET_DIAG_NOCOOKIE (~0U)
- * };
- *
- * @hide
- */
-public class StructInetDiagSockId {
- public static final int STRUCT_SIZE = 48;
-
- private final InetSocketAddress mLocSocketAddress;
- private final InetSocketAddress mRemSocketAddress;
- private final byte[] INET_DIAG_NOCOOKIE = new byte[]{
- (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
- (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
- private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
- mLocSocketAddress = loc;
- mRemSocketAddress = rem;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.order(BIG_ENDIAN);
- byteBuffer.putShort((short) mLocSocketAddress.getPort());
- byteBuffer.putShort((short) mRemSocketAddress.getPort());
- byteBuffer.put(mLocSocketAddress.getAddress().getAddress());
- if (mLocSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.put(mRemSocketAddress.getAddress().getAddress());
- if (mRemSocketAddress.getAddress() instanceof Inet4Address) {
- byteBuffer.put(IPV4_PADDING);
- }
- byteBuffer.order(ByteOrder.nativeOrder());
- byteBuffer.putInt(0);
- byteBuffer.put(INET_DIAG_NOCOOKIE);
- }
-
- @Override
- public String toString() {
- return "StructInetDiagSockId{ "
- + "idiag_sport{" + mLocSocketAddress.getPort() + "}, "
- + "idiag_dport{" + mRemSocketAddress.getPort() + "}, "
- + "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, "
- + "idiag_if{" + 0 + "} "
- + "idiag_cookie{INET_DIAG_NOCOOKIE}"
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNdMsg.java b/common/netlinkclient/src/android/net/netlink/StructNdMsg.java
deleted file mode 100644
index 64364df..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNdMsg.java
+++ /dev/null
@@ -1,165 +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.netlink;
-
-import android.system.OsConstants;
-import java.nio.ByteBuffer;
-
-
-/**
- * struct ndmsg
- *
- * see: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdMsg {
- // Already aligned.
- public static final int STRUCT_SIZE = 12;
-
- // Neighbor Cache Entry States
- public static final short NUD_NONE = 0x00;
- public static final short NUD_INCOMPLETE = 0x01;
- public static final short NUD_REACHABLE = 0x02;
- public static final short NUD_STALE = 0x04;
- public static final short NUD_DELAY = 0x08;
- public static final short NUD_PROBE = 0x10;
- public static final short NUD_FAILED = 0x20;
- public static final short NUD_NOARP = 0x40;
- public static final short NUD_PERMANENT = 0x80;
-
- public static String stringForNudState(short nudState) {
- switch (nudState) {
- case NUD_NONE: return "NUD_NONE";
- case NUD_INCOMPLETE: return "NUD_INCOMPLETE";
- case NUD_REACHABLE: return "NUD_REACHABLE";
- case NUD_STALE: return "NUD_STALE";
- case NUD_DELAY: return "NUD_DELAY";
- case NUD_PROBE: return "NUD_PROBE";
- case NUD_FAILED: return "NUD_FAILED";
- case NUD_NOARP: return "NUD_NOARP";
- case NUD_PERMANENT: return "NUD_PERMANENT";
- default:
- return "unknown NUD state: " + String.valueOf(nudState);
- }
- }
-
- public static boolean isNudStateConnected(short nudState) {
- return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0);
- }
-
- public static boolean isNudStateValid(short nudState) {
- return (isNudStateConnected(nudState) ||
- ((nudState & (NUD_PROBE|NUD_STALE|NUD_DELAY)) != 0));
- }
-
- // Neighbor Cache Entry Flags
- public static byte NTF_USE = (byte) 0x01;
- public static byte NTF_SELF = (byte) 0x02;
- public static byte NTF_MASTER = (byte) 0x04;
- public static byte NTF_PROXY = (byte) 0x08;
- public static byte NTF_ROUTER = (byte) 0x80;
-
- public static String stringForNudFlags(byte flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NTF_USE) != 0) {
- sb.append("NTF_USE");
- }
- if ((flags & NTF_SELF) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_SELF");
- }
- if ((flags & NTF_MASTER) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_MASTER");
- }
- if ((flags & NTF_PROXY) != 0) {
- if (sb.length() > 0) { sb.append("|");
- }
- sb.append("NTF_PROXY"); }
- if ((flags & NTF_ROUTER) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NTF_ROUTER");
- }
- return sb.toString();
- }
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNdMsg parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdMsg struct = new StructNdMsg();
- struct.ndm_family = byteBuffer.get();
- final byte pad1 = byteBuffer.get();
- final short pad2 = byteBuffer.getShort();
- struct.ndm_ifindex = byteBuffer.getInt();
- struct.ndm_state = byteBuffer.getShort();
- struct.ndm_flags = byteBuffer.get();
- struct.ndm_type = byteBuffer.get();
- return struct;
- }
-
- public byte ndm_family;
- public int ndm_ifindex;
- public short ndm_state;
- public byte ndm_flags;
- public byte ndm_type;
-
- public StructNdMsg() {
- ndm_family = (byte) OsConstants.AF_UNSPEC;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- byteBuffer.put(ndm_family);
- byteBuffer.put((byte) 0); // pad1
- byteBuffer.putShort((short) 0); // pad2
- byteBuffer.putInt(ndm_ifindex);
- byteBuffer.putShort(ndm_state);
- byteBuffer.put(ndm_flags);
- byteBuffer.put(ndm_type);
- }
-
- public boolean nudConnected() {
- return isNudStateConnected(ndm_state);
- }
-
- public boolean nudValid() {
- return isNudStateValid(ndm_state);
- }
-
- @Override
- public String toString() {
- final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")";
- final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")";
- return "StructNdMsg{ "
- + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, "
- + "ifindex{" + ndm_ifindex + "}, "
- + "state{" + stateStr + "}, "
- + "flags{" + flagsStr + "}, "
- + "type{" + ndm_type + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java b/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java
deleted file mode 100644
index 607aaba..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.netlink;
-
-import android.net.IpPrefix;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-
-/**
- * The PREF64 router advertisement option. RFC 8781.
- *
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Type | Length | Scaled Lifetime | PLC |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | |
- * + +
- * | Highest 96 bits of the Prefix |
- * + +
- * | |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- */
-public class StructNdOptPref64 extends NdOption {
- public static final int STRUCT_SIZE = 16;
- public static final int TYPE = 38;
- public static final byte LENGTH = 2;
-
- private static final String TAG = StructNdOptPref64.class.getSimpleName();
-
- /**
- * How many seconds the prefix is expected to remain valid.
- * Valid values are from 0 to 65528 in multiples of 8.
- */
- public final int lifetime;
- /** The NAT64 prefix. */
- @NonNull public final IpPrefix prefix;
-
- static int plcToPrefixLength(int plc) {
- switch (plc) {
- case 0: return 96;
- case 1: return 64;
- case 2: return 56;
- case 3: return 48;
- case 4: return 40;
- case 5: return 32;
- default:
- throw new IllegalArgumentException("Invalid prefix length code " + plc);
- }
- }
-
- static int prefixLengthToPlc(int prefixLength) {
- switch (prefixLength) {
- case 96: return 0;
- case 64: return 1;
- case 56: return 2;
- case 48: return 3;
- case 40: return 4;
- case 32: return 5;
- default:
- throw new IllegalArgumentException("Invalid prefix length " + prefixLength);
- }
- }
-
- /**
- * Returns the 2-byte "scaled lifetime and prefix length code" field: 13-bit lifetime, 3-bit PLC
- */
- static short getScaledLifetimePlc(int lifetime, int prefixLengthCode) {
- return (short) ((lifetime & 0xfff8) | (prefixLengthCode & 0x7));
- }
-
- public StructNdOptPref64(@NonNull IpPrefix prefix, int lifetime) {
- super((byte) TYPE, LENGTH);
-
- Objects.requireNonNull(prefix, "prefix must not be null");
- if (!(prefix.getAddress() instanceof Inet6Address)) {
- throw new IllegalArgumentException("Must be an IPv6 prefix: " + prefix);
- }
- prefixLengthToPlc(prefix.getPrefixLength()); // Throw if the prefix length is invalid.
- this.prefix = prefix;
-
- if (lifetime < 0 || lifetime > 0xfff8) {
- throw new IllegalArgumentException("Invalid lifetime " + lifetime);
- }
- this.lifetime = lifetime & 0xfff8;
- }
-
- private StructNdOptPref64(@NonNull ByteBuffer buf) {
- super(buf.get(), Byte.toUnsignedInt(buf.get()));
- if (type != TYPE) throw new IllegalArgumentException("Invalid type " + type);
- if (length != LENGTH) throw new IllegalArgumentException("Invalid length " + length);
-
- int scaledLifetimePlc = Short.toUnsignedInt(buf.getShort());
- lifetime = scaledLifetimePlc & 0xfff8;
-
- byte[] addressBytes = new byte[16];
- buf.get(addressBytes, 0, 12);
- InetAddress addr;
- try {
- addr = InetAddress.getByAddress(addressBytes);
- } catch (UnknownHostException e) {
- throw new AssertionError("16-byte array not valid InetAddress?");
- }
- prefix = new IpPrefix(addr, plcToPrefixLength(scaledLifetimePlc & 7));
- }
-
- /**
- * Parses an option from a {@link ByteBuffer}.
- *
- * @param buf The buffer from which to parse the option. The buffer's byte order must be
- * {@link java.nio.ByteOrder#BIG_ENDIAN}.
- * @return the parsed option, or {@code null} if the option could not be parsed successfully
- * (for example, if it was truncated, or if the prefix length code was wrong).
- */
- public static StructNdOptPref64 parse(@NonNull ByteBuffer buf) {
- if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
- try {
- return new StructNdOptPref64(buf);
- } catch (IllegalArgumentException e) {
- // Not great, but better than throwing an exception that might crash the caller.
- // Convention in this package is that null indicates that the option was truncated, so
- // callers must already handle it.
- Log.d(TAG, "Invalid PREF64 option: " + e);
- return null;
- }
- }
-
- protected void writeToByteBuffer(ByteBuffer buf) {
- super.writeToByteBuffer(buf);
- buf.putShort(getScaledLifetimePlc(lifetime, prefixLengthToPlc(prefix.getPrefixLength())));
- buf.put(prefix.getRawAddress(), 0, 12);
- }
-
- /** Outputs the wire format of the option to a new big-endian ByteBuffer. */
- public ByteBuffer toByteBuffer() {
- ByteBuffer buf = ByteBuffer.allocate(STRUCT_SIZE);
- writeToByteBuffer(buf);
- buf.flip();
- return buf;
- }
-
- @Override
- @NonNull
- public String toString() {
- return String.format("NdOptPref64(%s, %d)", prefix, lifetime);
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNdaCacheInfo.java b/common/netlinkclient/src/android/net/netlink/StructNdaCacheInfo.java
deleted file mode 100644
index 16cf563..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNdaCacheInfo.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2015 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.netlink;
-
-import android.system.Os;
-import android.system.OsConstants;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nda_cacheinfo
- *
- * see: <linux_src>/include/uapi/linux/neighbour.h
- *
- * @hide
- */
-public class StructNdaCacheInfo {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNdaCacheInfo parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- final StructNdaCacheInfo struct = new StructNdaCacheInfo();
- struct.ndm_used = byteBuffer.getInt();
- struct.ndm_confirmed = byteBuffer.getInt();
- struct.ndm_updated = byteBuffer.getInt();
- struct.ndm_refcnt = byteBuffer.getInt();
- return struct;
- }
-
- // TODO: investigate whether this can change during device runtime and
- // decide what (if anything) should be done about that.
- private static final long CLOCK_TICKS_PER_SECOND = Os.sysconf(OsConstants._SC_CLK_TCK);
-
- private static long ticksToMilliSeconds(int intClockTicks) {
- final long longClockTicks = (long) intClockTicks & 0xffffffff;
- return (longClockTicks * 1000) / CLOCK_TICKS_PER_SECOND;
- }
-
- /**
- * Explanatory notes, for reference.
- *
- * Before being returned to user space, the neighbor entry times are
- * converted to clock_t's like so:
- *
- * ndm_used = jiffies_to_clock_t(now - neigh->used);
- * ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
- * ndm_updated = jiffies_to_clock_t(now - neigh->updated);
- *
- * meaning that these values are expressed as "clock ticks ago". To
- * convert these clock ticks to seconds divide by sysconf(_SC_CLK_TCK).
- * When _SC_CLK_TCK is 100, for example, the ndm_* times are expressed
- * in centiseconds.
- *
- * These values are unsigned, but fortunately being expressed as "some
- * clock ticks ago", these values are typically very small (and
- * 2^31 centiseconds = 248 days).
- *
- * By observation, it appears that:
- * ndm_used: the last time ARP/ND took place for this neighbor
- * ndm_confirmed: the last time ARP/ND succeeded for this neighbor OR
- * higher layer confirmation (TCP or MSG_CONFIRM)
- * was received
- * ndm_updated: the time when the current NUD state was entered
- */
- public int ndm_used;
- public int ndm_confirmed;
- public int ndm_updated;
- public int ndm_refcnt;
-
- public StructNdaCacheInfo() {}
-
- public long lastUsed() {
- return ticksToMilliSeconds(ndm_used);
- }
-
- public long lastConfirmed() {
- return ticksToMilliSeconds(ndm_confirmed);
- }
-
- public long lastUpdated() {
- return ticksToMilliSeconds(ndm_updated);
- }
-
- @Override
- public String toString() {
- return "NdaCacheInfo{ "
- + "ndm_used{" + lastUsed() + "}, "
- + "ndm_confirmed{" + lastConfirmed() + "}, "
- + "ndm_updated{" + lastUpdated() + "}, "
- + "ndm_refcnt{" + ndm_refcnt + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNfGenMsg.java b/common/netlinkclient/src/android/net/netlink/StructNfGenMsg.java
deleted file mode 100644
index 7f247f5..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNfGenMsg.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2017 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.netlink;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-
-/**
- * struct nfgenmsg
- *
- * see <linux_src>/include/uapi/linux/netfilter/nfnetlink.h
- *
- * @hide
- */
-public class StructNfGenMsg {
- public static final int STRUCT_SIZE = 2 + Short.BYTES;
-
- public static final int NFNETLINK_V0 = 0;
-
- final public byte nfgen_family;
- final public byte version;
- final public short res_id; // N.B.: this is big endian in the kernel
-
- /**
- * Parses a netfilter netlink header from a {@link ByteBuffer}.
- *
- * @param byteBuffer The buffer from which to parse the netfilter netlink header.
- * @return the parsed netfilter netlink header, or {@code null} if the netfilter netlink header
- * could not be parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructNfGenMsg parse(@NonNull ByteBuffer byteBuffer) {
- Objects.requireNonNull(byteBuffer);
-
- if (!hasAvailableSpace(byteBuffer)) return null;
-
- final byte nfgen_family = byteBuffer.get();
- final byte version = byteBuffer.get();
-
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- final short res_id = byteBuffer.getShort();
- byteBuffer.order(originalOrder);
-
- return new StructNfGenMsg(nfgen_family, version, res_id);
- }
-
- public StructNfGenMsg(byte family, byte ver, short id) {
- nfgen_family = family;
- version = ver;
- res_id = id;
- }
-
- public StructNfGenMsg(byte family) {
- nfgen_family = family;
- version = (byte) NFNETLINK_V0;
- res_id = (short) 0;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- byteBuffer.put(nfgen_family);
- byteBuffer.put(version);
-
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- byteBuffer.putShort(res_id);
- byteBuffer.order(originalOrder);
- }
-
- private static boolean hasAvailableSpace(@NonNull ByteBuffer byteBuffer) {
- return byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- @Override
- public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(nfgen_family);
-
- return "NfGenMsg{ "
- + "nfgen_family{" + familyStr + "}, "
- + "version{" + Byte.toUnsignedInt(version) + "}, "
- + "res_id{" + Short.toUnsignedInt(res_id) + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNlAttr.java b/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
deleted file mode 100644
index b6e1d3f..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
+++ /dev/null
@@ -1,284 +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.netlink;
-
-import androidx.annotation.Nullable;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-
-/**
- * struct nlattr
- *
- * see: <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlAttr {
- // Already aligned.
- public static final int NLA_HEADERLEN = 4;
- public static final int NLA_F_NESTED = (1 << 15);
-
- public static short makeNestedType(short type) {
- return (short) (type | NLA_F_NESTED);
- }
-
- // Return a (length, type) object only, without consuming any bytes in
- // |byteBuffer| and without copying or interpreting any value bytes.
- // This is used for scanning over a packed set of struct nlattr's,
- // looking for instances of a particular type.
- public static StructNlAttr peek(ByteBuffer byteBuffer) {
- if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) {
- return null;
- }
- final int baseOffset = byteBuffer.position();
-
- final StructNlAttr struct = new StructNlAttr();
- final ByteOrder originalOrder = byteBuffer.order();
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- struct.nla_len = byteBuffer.getShort();
- struct.nla_type = byteBuffer.getShort();
- } finally {
- byteBuffer.order(originalOrder);
- }
-
- byteBuffer.position(baseOffset);
- if (struct.nla_len < NLA_HEADERLEN) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- public static StructNlAttr parse(ByteBuffer byteBuffer) {
- final StructNlAttr struct = peek(byteBuffer);
- if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) {
- return null;
- }
-
- final int baseOffset = byteBuffer.position();
- byteBuffer.position(baseOffset + NLA_HEADERLEN);
-
- int valueLen = ((int) struct.nla_len) & 0xffff;
- valueLen -= NLA_HEADERLEN;
- if (valueLen > 0) {
- struct.nla_value = new byte[valueLen];
- byteBuffer.get(struct.nla_value, 0, valueLen);
- byteBuffer.position(baseOffset + struct.getAlignedLength());
- }
- return struct;
- }
-
- /**
- * Find next netlink attribute with a given type from {@link ByteBuffer}.
- *
- * @param attrType The given netlink attribute type is requested for.
- * @param byteBuffer The buffer from which to find the netlink attribute.
- * @return the found netlink attribute, or {@code null} if the netlink attribute could not be
- * found or parsed successfully (for example, if it was truncated).
- */
- @Nullable
- public static StructNlAttr findNextAttrOfType(short attrType,
- @Nullable ByteBuffer byteBuffer) {
- while (byteBuffer != null && byteBuffer.remaining() > 0) {
- final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer);
- if (nlAttr == null) {
- break;
- }
- if (nlAttr.nla_type == attrType) {
- return StructNlAttr.parse(byteBuffer);
- }
- if (byteBuffer.remaining() < nlAttr.getAlignedLength()) {
- break;
- }
- byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength());
- }
- return null;
- }
-
- public short nla_len = (short) NLA_HEADERLEN;
- public short nla_type;
- public byte[] nla_value;
-
- public StructNlAttr() {}
-
- public StructNlAttr(short type, byte value) {
- nla_type = type;
- setValue(new byte[1]);
- nla_value[0] = value;
- }
-
- public StructNlAttr(short type, short value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, short value, ByteOrder order) {
- nla_type = type;
- setValue(new byte[Short.BYTES]);
- final ByteBuffer buf = getValueAsByteBuffer();
- final ByteOrder originalOrder = buf.order();
- try {
- buf.order(order);
- buf.putShort(value);
- } finally {
- buf.order(originalOrder);
- }
- }
-
- public StructNlAttr(short type, int value) {
- this(type, value, ByteOrder.nativeOrder());
- }
-
- public StructNlAttr(short type, int value, ByteOrder order) {
- nla_type = type;
- setValue(new byte[Integer.BYTES]);
- final ByteBuffer buf = getValueAsByteBuffer();
- final ByteOrder originalOrder = buf.order();
- try {
- buf.order(order);
- buf.putInt(value);
- } finally {
- buf.order(originalOrder);
- }
- }
-
- public StructNlAttr(short type, InetAddress ip) {
- nla_type = type;
- setValue(ip.getAddress());
- }
-
- public StructNlAttr(short type, StructNlAttr... nested) {
- this();
- nla_type = makeNestedType(type);
-
- int payloadLength = 0;
- for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
- setValue(new byte[payloadLength]);
-
- final ByteBuffer buf = getValueAsByteBuffer();
- for (StructNlAttr nla : nested) {
- nla.pack(buf);
- }
- }
-
- public int getAlignedLength() {
- return NetlinkConstants.alignedLengthOf(nla_len);
- }
-
- /**
- * Get attribute value as BE16.
- */
- public short getValueAsBe16(short defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Short.BYTES) {
- return defaultValue;
- }
- final ByteOrder originalOrder = byteBuffer.order();
- try {
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- return byteBuffer.getShort();
- } finally {
- byteBuffer.order(originalOrder);
- }
- }
-
- public int getValueAsBe32(int defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
- return defaultValue;
- }
- final ByteOrder originalOrder = byteBuffer.order();
- try {
- byteBuffer.order(ByteOrder.BIG_ENDIAN);
- return byteBuffer.getInt();
- } finally {
- byteBuffer.order(originalOrder);
- }
- }
-
- public ByteBuffer getValueAsByteBuffer() {
- if (nla_value == null) { return null; }
- final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
- // By convention, all buffers in this library are in native byte order because netlink is in
- // native byte order. It's the order that is used by NetlinkSocket.recvMessage and the only
- // order accepted by NetlinkMessage.parse.
- byteBuffer.order(ByteOrder.nativeOrder());
- return byteBuffer;
- }
-
- /**
- * Get attribute value as byte.
- */
- public byte getValueAsByte(byte defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Byte.BYTES) {
- return defaultValue;
- }
- return getValueAsByteBuffer().get();
- }
-
- public int getValueAsInt(int defaultValue) {
- final ByteBuffer byteBuffer = getValueAsByteBuffer();
- if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
- return defaultValue;
- }
- return getValueAsByteBuffer().getInt();
- }
-
- public InetAddress getValueAsInetAddress() {
- if (nla_value == null) { return null; }
-
- try {
- return InetAddress.getByAddress(nla_value);
- } catch (UnknownHostException ignored) {
- return null;
- }
- }
-
- public void pack(ByteBuffer byteBuffer) {
- final ByteOrder originalOrder = byteBuffer.order();
- final int originalPosition = byteBuffer.position();
-
- byteBuffer.order(ByteOrder.nativeOrder());
- try {
- byteBuffer.putShort(nla_len);
- byteBuffer.putShort(nla_type);
- if (nla_value != null) byteBuffer.put(nla_value);
- } finally {
- byteBuffer.order(originalOrder);
- }
- byteBuffer.position(originalPosition + getAlignedLength());
- }
-
- private void setValue(byte[] value) {
- nla_value = value;
- nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
- }
-
- @Override
- public String toString() {
- return "StructNlAttr{ "
- + "nla_len{" + nla_len + "}, "
- + "nla_type{" + nla_type + "}, "
- + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNlMsgErr.java b/common/netlinkclient/src/android/net/netlink/StructNlMsgErr.java
deleted file mode 100644
index 9ea4364..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNlMsgErr.java
+++ /dev/null
@@ -1,68 +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.netlink;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsgerr
- *
- * see <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgErr {
- public static final int STRUCT_SIZE = Integer.BYTES + StructNlMsgHdr.STRUCT_SIZE;
-
- public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNlMsgErr parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgErr struct = new StructNlMsgErr();
- struct.error = byteBuffer.getInt();
- struct.msg = StructNlMsgHdr.parse(byteBuffer);
- return struct;
- }
-
- public int error;
- public StructNlMsgHdr msg;
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(error);
- if (msg != null) {
- msg.pack(byteBuffer);
- }
- }
-
- @Override
- public String toString() {
- return "StructNlMsgErr{ "
- + "error{" + error + "}, "
- + "msg{" + (msg == null ? "" : msg.toString()) + "} "
- + "}";
- }
-}
diff --git a/common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java b/common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java
deleted file mode 100644
index 55a649d..0000000
--- a/common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java
+++ /dev/null
@@ -1,158 +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.netlink;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.nio.ByteBuffer;
-
-
-/**
- * struct nlmsghdr
- *
- * see <linux_src>/include/uapi/linux/netlink.h
- *
- * @hide
- */
-public class StructNlMsgHdr {
- // Already aligned.
- public static final int STRUCT_SIZE = 16;
-
- public static final short NLM_F_REQUEST = 0x0001;
- public static final short NLM_F_MULTI = 0x0002;
- public static final short NLM_F_ACK = 0x0004;
- public static final short NLM_F_ECHO = 0x0008;
- // Flags for a GET request.
- public static final short NLM_F_ROOT = 0x0100;
- public static final short NLM_F_MATCH = 0x0200;
- public static final short NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH;
- // Flags for a NEW request.
- public static final short NLM_F_REPLACE = 0x100;
- public static final short NLM_F_EXCL = 0x200;
- public static final short NLM_F_CREATE = 0x400;
- public static final short NLM_F_APPEND = 0x800;
-
- // TODO: Probably need to distinguish the flags which have the same value. For example,
- // NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200).
- public static String stringForNlMsgFlags(short flags) {
- final StringBuilder sb = new StringBuilder();
- if ((flags & NLM_F_REQUEST) != 0) {
- sb.append("NLM_F_REQUEST");
- }
- if ((flags & NLM_F_MULTI) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_MULTI");
- }
- if ((flags & NLM_F_ACK) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ACK");
- }
- if ((flags & NLM_F_ECHO) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ECHO");
- }
- if ((flags & NLM_F_ROOT) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_ROOT");
- }
- if ((flags & NLM_F_MATCH) != 0) {
- if (sb.length() > 0) { sb.append("|"); }
- sb.append("NLM_F_MATCH");
- }
- return sb.toString();
- }
-
- public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
- return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
- }
-
- public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
- if (!hasAvailableSpace(byteBuffer)) { return null; }
-
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the exception
- // of usage within unittests.
- final StructNlMsgHdr struct = new StructNlMsgHdr();
- struct.nlmsg_len = byteBuffer.getInt();
- struct.nlmsg_type = byteBuffer.getShort();
- struct.nlmsg_flags = byteBuffer.getShort();
- struct.nlmsg_seq = byteBuffer.getInt();
- struct.nlmsg_pid = byteBuffer.getInt();
-
- if (struct.nlmsg_len < STRUCT_SIZE) {
- // Malformed.
- return null;
- }
- return struct;
- }
-
- public int nlmsg_len;
- public short nlmsg_type;
- public short nlmsg_flags;
- public int nlmsg_seq;
- public int nlmsg_pid;
-
- public StructNlMsgHdr() {
- nlmsg_len = 0;
- nlmsg_type = 0;
- nlmsg_flags = 0;
- nlmsg_seq = 0;
- nlmsg_pid = 0;
- }
-
- public void pack(ByteBuffer byteBuffer) {
- // The ByteOrder must have already been set by the caller. In most
- // cases ByteOrder.nativeOrder() is correct, with the possible
- // exception of usage within unittests.
- byteBuffer.putInt(nlmsg_len);
- byteBuffer.putShort(nlmsg_type);
- byteBuffer.putShort(nlmsg_flags);
- byteBuffer.putInt(nlmsg_seq);
- byteBuffer.putInt(nlmsg_pid);
- }
-
- @Override
- public String toString() {
- return toString(null /* unknown netlink family */);
- }
-
- /**
- * Transform a netlink header into a string. The netlink family is required for transforming
- * a netlink type integer into a string.
- * @param nlFamily netlink family. Using Integer will not incur autoboxing penalties because
- * family values are small, and all Integer objects between -128 and 127 are
- * statically cached. See Integer.IntegerCache.
- * @return A list of header elements.
- */
- @NonNull
- public String toString(@Nullable Integer nlFamily) {
- final String typeStr = "" + nlmsg_type
- + "(" + (nlFamily == null
- ? "" : NetlinkConstants.stringForNlMsgType(nlmsg_type, nlFamily))
- + ")";
- final String flagsStr = "" + nlmsg_flags
- + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
- return "StructNlMsgHdr{ "
- + "nlmsg_len{" + nlmsg_len + "}, "
- + "nlmsg_type{" + typeStr + "}, "
- + "nlmsg_flags{" + flagsStr + ")}, "
- + "nlmsg_seq{" + nlmsg_seq + "}, "
- + "nlmsg_pid{" + nlmsg_pid + "} "
- + "}";
- }
-}
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index dc91881..c344d07 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -15,6 +15,10 @@
//
// AIDL interfaces between the core system and the networking mainline module.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
aidl_interface {
name: "ipmemorystore-aidl-interfaces",
local_include_dir: "src",
@@ -68,7 +72,7 @@
// For framework parcelables.
"frameworks/base/core/java",
// For API parcelables in connectivity
- "frameworks/base/packages/Connectivity/framework/src",
+ "packages/modules/Connectivity/framework/aidl-export",
"frameworks/native/aidl/binder", // For PersistableBundle.aidl
],
srcs: [
@@ -117,7 +121,7 @@
enabled: false,
},
},
- imports: ["ipmemorystore-aidl-interfaces"],
+ imports: ["ipmemorystore-aidl-interfaces-V10"],
versions: [
"1",
"2",
@@ -129,6 +133,8 @@
"8",
"9",
"10",
+ "11",
+ "12",
],
// TODO: have tethering depend on networkstack-client and set visibility to private
visibility: [
@@ -141,25 +147,38 @@
java_library {
name: "networkstack-client",
sdk_version: "system_current",
- // this is part of updatable modules(NetworkStack) which targets 29(Q)
+ // this is part of updatable modules(NetworkStack) which runs on Q and above
min_sdk_version: "29",
srcs: [
":framework-annotations",
+ "src/android/net/ip/**/*.java",
+ "src/android/net/IpMemoryStore.java",
"src/android/net/IpMemoryStoreClient.java",
"src/android/net/ipmemorystore/**/*.java",
+ "src/android/net/NetworkMonitorManager.java",
"src/android/net/networkstack/**/*.java",
"src/android/net/networkstack/aidl/quirks/**/*.java",
"src/android/net/shared/**/*.java",
+ "src/android/net/util/**/*.java",
+ ],
+ libs: [
+ "net-utils-framework-common", // XXX for IpUtils.java only
],
static_libs: [
- "ipmemorystore-aidl-interfaces-java",
- "networkstack-aidl-interfaces-java",
+ "ipmemorystore-aidl-interfaces-V10-java",
+ "networkstack-aidl-interfaces-V12-java",
],
visibility: [
- "//frameworks/base/packages/Tethering",
+ "//frameworks/base/packages/Connectivity/service",
"//packages/modules/Connectivity/Tethering",
+ "//packages/modules/Connectivity/service",
"//frameworks/base/services/net",
"//frameworks/opt/net/wifi/service",
+ "//packages/apps/Bluetooth",
"//packages/modules/NetworkStack",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ ],
}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
index bf7a26d..048e84c 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStoreCallbacks.aidl
index 2024391..7dbbc98 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStoreCallbacks.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStoreCallbacks.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/Blob.aidl
index 8a1b57e..4300c83 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/Blob.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/Blob.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
index e711272..3a263e2 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
index 4abecb9..c663ccf 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
index 05c48b3..3740e15 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
index 0bc8c5e..9d87fbb 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
index cf30fa1..1e6a41c 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusListener.aidl
index e71de47..dccdf27 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusListener.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
index 2ac7644..227785d 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
index 42a1feb..377a3ec 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/StatusParcelable.aidl
index 1bea082..59b96cd 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/StatusParcelable.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/StatusParcelable.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable.aidl
index e2ecbb4..c01564b 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
//
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/.hash b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/.hash
new file mode 100644
index 0000000..2914d2a
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/.hash
@@ -0,0 +1 @@
+7fecd0a7a6d978705afad88c5e492613cc46e2cb
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DataStallReportParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DataStallReportParcelable.aidl
new file mode 100644
index 0000000..771deda
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DataStallReportParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DataStallReportParcelable {
+ long timestampMillis = 0;
+ int detectionMethod = 1;
+ int tcpPacketFailRate = 2;
+ int tcpMetricsCollectionPeriodMillis = 3;
+ int dnsConsecutiveTimeouts = 4;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31f2194
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,44 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ @nullable String serverHostName;
+ @nullable String captivePortalApiUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..d92196d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitor.aidl
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_RESULT_SKIPPED = 4;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..36eda8e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor) = 0;
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl) = 1;
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config) = 2;
+ oneway void showProvisioningNotification(String action, String packageName) = 3;
+ oneway void hideProvisioningNotification() = 4;
+ oneway void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) = 5;
+ oneway void notifyNetworkTestedWithExtras(in android.net.NetworkTestResultParcelable result) = 6;
+ oneway void notifyDataStallSuspected(in android.net.DataStallReportParcelable report) = 7;
+ oneway void notifyCaptivePortalDataChanged(in android.net.CaptivePortalData data) = 8;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..8120ffc
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+ oneway void allowTestUid(int uid, in android.net.INetworkStackStatusCallback cb);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..0b6b778
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InformationElementParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InformationElementParcelable.aidl
new file mode 100644
index 0000000..6103774
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InformationElementParcelable.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InformationElementParcelable {
+ int id;
+ byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..6a597e6
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2InformationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2InformationParcelable.aidl
new file mode 100644
index 0000000..83796ee
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2InformationParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2InformationParcelable {
+ String l2Key;
+ String cluster;
+ android.net.MacAddress bssid;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2PacketParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2PacketParcelable.aidl
new file mode 100644
index 0000000..4b3fff5
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2PacketParcelable.aidl
@@ -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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2PacketParcelable {
+ android.net.MacAddress dstMacAddress;
+ byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..18cf954
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NetworkTestResultParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NetworkTestResultParcelable.aidl
new file mode 100644
index 0000000..4d6d5a2
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NetworkTestResultParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NetworkTestResultParcelable {
+ long timestampMillis;
+ int result;
+ int probesSucceeded;
+ int probesAttempted;
+ String redirectUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..1457caf
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..0b7a7a1
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,54 @@
+/*
+**
+** 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.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+ boolean enablePreconnection;
+ @nullable android.net.ScanResultInfoParcelable scanResultInfo;
+ @nullable android.net.Layer2InformationParcelable layer2Info;
+ @nullable List<android.net.networkstack.aidl.dhcp.DhcpOption> options;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ScanResultInfoParcelable.aidl
new file mode 100644
index 0000000..94fc27f
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ScanResultInfoParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable ScanResultInfoParcelable {
+ String ssid;
+ String bssid;
+ android.net.InformationElementParcelable[] informationElements;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..0e1c21c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpLeaseParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpLeaseParcelable.aidl
new file mode 100644
index 0000000..3cd8860
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpLeaseParcelable.aidl
@@ -0,0 +1,43 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpLeaseParcelable {
+ byte[] clientId;
+ byte[] hwAddr;
+ int netAddr;
+ int prefixLength;
+ long expTime;
+ String hostname;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..fa412cb
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,48 @@
+/**
+ *
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+ int singleClientAddr = 0;
+ boolean changePrefixOnDecline = false;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpEventCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpEventCallbacks.aidl
new file mode 100644
index 0000000..9312f47
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpEventCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+interface IDhcpEventCallbacks {
+ oneway void onLeasesChanged(in List<android.net.dhcp.DhcpLeaseParcelable> newLeases);
+ oneway void onNewPrefixRequest(in android.net.IpPrefix currentPrefix);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..1109f35
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb) = 0;
+ oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpEventCallbacks eventCb) = 3;
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb) = 1;
+ oneway void stop(in android.net.INetworkStackStatusCallback cb) = 2;
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..ab8577c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..1fe4c4c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClient.aidl
@@ -0,0 +1,52 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+/* @hide */
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String cluster);
+ oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+ oneway void notifyPreconnectionComplete(boolean success);
+ oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..488510d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,51 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+/* @hide */
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+ oneway void onPreconnectionStart(in List<android.net.Layer2PacketParcelable> packets);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/networkstack/aidl/dhcp/DhcpOption.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
new file mode 100644
index 0000000..eea3e0d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
@@ -0,0 +1,39 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.networkstack.aidl.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpOption {
+ byte type;
+ @nullable byte[] value;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/.hash b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/.hash
new file mode 100644
index 0000000..e96fe34
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/.hash
@@ -0,0 +1 @@
+ca534b24b8f1e946a36977f391a156016ea7ef4a
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DataStallReportParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DataStallReportParcelable.aidl
new file mode 100644
index 0000000..771deda
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DataStallReportParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DataStallReportParcelable {
+ long timestampMillis = 0;
+ int detectionMethod = 1;
+ int tcpPacketFailRate = 2;
+ int tcpMetricsCollectionPeriodMillis = 3;
+ int dnsConsecutiveTimeouts = 4;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31f2194
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,44 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ @nullable String serverHostName;
+ @nullable String captivePortalApiUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..d92196d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitor.aidl
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_RESULT_SKIPPED = 4;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..36eda8e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor) = 0;
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl) = 1;
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config) = 2;
+ oneway void showProvisioningNotification(String action, String packageName) = 3;
+ oneway void hideProvisioningNotification() = 4;
+ oneway void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) = 5;
+ oneway void notifyNetworkTestedWithExtras(in android.net.NetworkTestResultParcelable result) = 6;
+ oneway void notifyDataStallSuspected(in android.net.DataStallReportParcelable report) = 7;
+ oneway void notifyCaptivePortalDataChanged(in android.net.CaptivePortalData data) = 8;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..8120ffc
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+ oneway void allowTestUid(int uid, in android.net.INetworkStackStatusCallback cb);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..0b6b778
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InformationElementParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InformationElementParcelable.aidl
new file mode 100644
index 0000000..6103774
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InformationElementParcelable.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InformationElementParcelable {
+ int id;
+ byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..6a597e6
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2InformationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2InformationParcelable.aidl
new file mode 100644
index 0000000..83796ee
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2InformationParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2InformationParcelable {
+ String l2Key;
+ String cluster;
+ android.net.MacAddress bssid;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2PacketParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2PacketParcelable.aidl
new file mode 100644
index 0000000..4b3fff5
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2PacketParcelable.aidl
@@ -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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2PacketParcelable {
+ android.net.MacAddress dstMacAddress;
+ byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..18cf954
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NetworkTestResultParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NetworkTestResultParcelable.aidl
new file mode 100644
index 0000000..4d6d5a2
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NetworkTestResultParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NetworkTestResultParcelable {
+ long timestampMillis;
+ int result;
+ int probesSucceeded;
+ int probesAttempted;
+ String redirectUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..1457caf
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..9ecd110
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,62 @@
+/*
+**
+** 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.
+*/
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable ProvisioningConfigurationParcelable {
+ /**
+ * @deprecated use ipv4ProvisioningMode instead.
+ */
+ boolean enableIPv4;
+ /**
+ * @deprecated use ipv6ProvisioningMode instead.
+ */
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+ boolean enablePreconnection;
+ @nullable android.net.ScanResultInfoParcelable scanResultInfo;
+ @nullable android.net.Layer2InformationParcelable layer2Info;
+ @nullable List<android.net.networkstack.aidl.dhcp.DhcpOption> options;
+ int ipv4ProvisioningMode;
+ int ipv6ProvisioningMode;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ScanResultInfoParcelable.aidl
new file mode 100644
index 0000000..94fc27f
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ScanResultInfoParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable ScanResultInfoParcelable {
+ String ssid;
+ String bssid;
+ android.net.InformationElementParcelable[] informationElements;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..0e1c21c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpLeaseParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpLeaseParcelable.aidl
new file mode 100644
index 0000000..3cd8860
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpLeaseParcelable.aidl
@@ -0,0 +1,43 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpLeaseParcelable {
+ byte[] clientId;
+ byte[] hwAddr;
+ int netAddr;
+ int prefixLength;
+ long expTime;
+ String hostname;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..fa412cb
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,48 @@
+/**
+ *
+ * Copyright (C) 2018 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+ int singleClientAddr = 0;
+ boolean changePrefixOnDecline = false;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpEventCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpEventCallbacks.aidl
new file mode 100644
index 0000000..9312f47
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpEventCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+interface IDhcpEventCallbacks {
+ oneway void onLeasesChanged(in List<android.net.dhcp.DhcpLeaseParcelable> newLeases);
+ oneway void onNewPrefixRequest(in android.net.IpPrefix currentPrefix);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..1109f35
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb) = 0;
+ oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpEventCallbacks eventCb) = 3;
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb) = 1;
+ oneway void stop(in android.net.INetworkStackStatusCallback cb) = 2;
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..ab8577c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..a97511e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClient.aidl
@@ -0,0 +1,58 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+/* @hide */
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String cluster);
+ oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+ oneway void notifyPreconnectionComplete(boolean success);
+ oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info);
+ const int PROV_IPV4_DISABLED = 0;
+ const int PROV_IPV4_STATIC = 1;
+ const int PROV_IPV4_DHCP = 2;
+ const int PROV_IPV6_DISABLED = 0;
+ const int PROV_IPV6_SLAAC = 1;
+ const int PROV_IPV6_LINKLOCAL = 2;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..488510d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,51 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+/* @hide */
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+ oneway void onPreconnectionStart(in List<android.net.Layer2PacketParcelable> packets);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/networkstack/aidl/dhcp/DhcpOption.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
new file mode 100644
index 0000000..eea3e0d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
@@ -0,0 +1,39 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.networkstack.aidl.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpOption {
+ byte type;
+ @nullable byte[] value;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DataStallReportParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DataStallReportParcelable.aidl
index 0f860a5..771deda 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DataStallReportParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DataStallReportParcelable.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DhcpResultsParcelable.aidl
index 4445be7..31f2194 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DhcpResultsParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/DhcpResultsParcelable.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitor.aidl
index db9145f..d92196d 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitor.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitor.aidl
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -35,6 +50,7 @@
const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
const int NETWORK_VALIDATION_RESULT_VALID = 1;
const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_RESULT_SKIPPED = 4;
const int NETWORK_VALIDATION_PROBE_DNS = 4;
const int NETWORK_VALIDATION_PROBE_HTTP = 8;
const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitorCallbacks.aidl
index b2685ad..36eda8e 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitorCallbacks.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkMonitorCallbacks.aidl
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackConnector.aidl
index 396b42a..8120ffc 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackConnector.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackConnector.aidl
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackStatusCallback.aidl
index 97c9970..0b6b778 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackStatusCallback.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/INetworkStackStatusCallback.aidl
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InformationElementParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InformationElementParcelable.aidl
index 77fca83..6103774 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InformationElementParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InformationElementParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InitialConfigurationParcelable.aidl
index 6137305..6a597e6 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InitialConfigurationParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/InitialConfigurationParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2InformationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2InformationParcelable.aidl
index d3adbb3..83796ee 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2InformationParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2InformationParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2PacketParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2PacketParcelable.aidl
index b45f6da..4b3fff5 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2PacketParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/Layer2PacketParcelable.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NattKeepalivePacketDataParcelable.aidl
index 7634ac9..18cf954 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NattKeepalivePacketDataParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NetworkTestResultParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NetworkTestResultParcelable.aidl
index 1d0bbbe..4d6d5a2 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NetworkTestResultParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/NetworkTestResultParcelable.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl
index c6d6361..1457caf 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/PrivateDnsConfigParcel.aidl
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ProvisioningConfigurationParcelable.aidl
index 171817c..9ecd110 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ProvisioningConfigurationParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ProvisioningConfigurationParcelable.aidl
@@ -1,3 +1,19 @@
+/*
+**
+** 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.
+*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -19,7 +35,13 @@
package android.net;
@JavaDerive(toString=true)
parcelable ProvisioningConfigurationParcelable {
+ /**
+ * @deprecated use ipv4ProvisioningMode instead.
+ */
boolean enableIPv4;
+ /**
+ * @deprecated use ipv6ProvisioningMode instead.
+ */
boolean enableIPv6;
boolean usingMultinetworkPolicyTracker;
boolean usingIpReachabilityMonitor;
@@ -35,4 +57,6 @@
@nullable android.net.ScanResultInfoParcelable scanResultInfo;
@nullable android.net.Layer2InformationParcelable layer2Info;
@nullable List<android.net.networkstack.aidl.dhcp.DhcpOption> options;
+ int ipv4ProvisioningMode;
+ int ipv6ProvisioningMode;
}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ScanResultInfoParcelable.aidl
index 4646ede..94fc27f 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ScanResultInfoParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ScanResultInfoParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/TcpKeepalivePacketDataParcelable.aidl
index 00f15da..0e1c21c 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/TcpKeepalivePacketDataParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpLeaseParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpLeaseParcelable.aidl
index b0a0f0f..3cd8860 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpLeaseParcelable.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpLeaseParcelable.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpServingParamsParcel.aidl
index d56ef8e..fa412cb 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpServingParamsParcel.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -1,3 +1,19 @@
+/**
+ *
+ * Copyright (C) 2018 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.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl
index 8f3288e..9312f47 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpEventCallbacks.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl
index 83cebdf..1109f35 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServer.aidl
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServerCallbacks.aidl
index 35da06c..ab8577c 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServerCallbacks.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -1,3 +1,18 @@
+/**
+ * Copyright (c) 2018, 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClient.aidl
index 5607b2a..a97511e 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClient.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClient.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
@@ -34,4 +49,10 @@
oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
oneway void notifyPreconnectionComplete(boolean success);
oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info);
+ const int PROV_IPV4_DISABLED = 0;
+ const int PROV_IPV4_STATIC = 1;
+ const int PROV_IPV4_DHCP = 2;
+ const int PROV_IPV6_DISABLED = 0;
+ const int PROV_IPV6_SLAAC = 1;
+ const int PROV_IPV6_LINKLOCAL = 2;
}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClientCallbacks.aidl
index 9a84784..488510d 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClientCallbacks.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/ip/IIpClientCallbacks.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/dhcp/DhcpOption.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
index c97212b..eea3e0d 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
@@ -1,3 +1,18 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
diff --git a/common/networkstackclient/src/android/net/INetworkMonitor.aidl b/common/networkstackclient/src/android/net/INetworkMonitor.aidl
index 3fc81a3..b124734 100644
--- a/common/networkstackclient/src/android/net/INetworkMonitor.aidl
+++ b/common/networkstackclient/src/android/net/INetworkMonitor.aidl
@@ -44,10 +44,16 @@
// are set, then it's equal to NETWORK_TEST_RESULT_INVALID. If NETWORK_VALIDATION_RESULT_VALID
// is set, then the network validates and equal to NETWORK_TEST_RESULT_VALID. If
// NETWORK_VALIDATION_RESULT_PARTIAL is set, then the network has partial connectivity which
- // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. NETWORK_VALIDATION_PROBE_* is set
- // when the specific probe result of the network is resolved.
+ // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. Networks receiving validation that both
+ // do not require validation and are not validated will have NETWORK_VALIDATION_RESULT_SKIPPED
+ // set. NETWORK_VALIDATION_PROBE_* is set when the specific probe result of the network is
+ // resolved.
const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+ const int NETWORK_VALIDATION_RESULT_SKIPPED = 0x04;
+
+ // NETWORK_VALIDATION_RESULT_* and NETWORK_VALIDATION_PROBE_* are independent values sent in
+ // different ints.
const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
diff --git a/common/networkstackclient/src/android/net/IpMemoryStore.java b/common/networkstackclient/src/android/net/IpMemoryStore.java
new file mode 100644
index 0000000..f2c1d35
--- /dev/null
+++ b/common/networkstackclient/src/android/net/IpMemoryStore.java
@@ -0,0 +1,98 @@
+/*
+ * 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.content.Context;
+import android.net.networkstack.ModuleNetworkStackClient;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+/**
+ * Manager class used to communicate with the ip memory store service in the network stack,
+ * which is running in a separate module.
+ * @hide
+*/
+public class IpMemoryStore extends IpMemoryStoreClient {
+ private static final String TAG = IpMemoryStore.class.getSimpleName();
+ @NonNull private final CompletableFuture<IIpMemoryStore> mService;
+ @NonNull private final AtomicReference<CompletableFuture<IIpMemoryStore>> mTailNode;
+
+ public IpMemoryStore(@NonNull final Context context) {
+ super(context);
+ mService = new CompletableFuture<>();
+ mTailNode = new AtomicReference<CompletableFuture<IIpMemoryStore>>(mService);
+ getModuleNetworkStackClient(context).fetchIpMemoryStore(
+ new IIpMemoryStoreCallbacks.Stub() {
+ @Override
+ public void onIpMemoryStoreFetched(@NonNull final IIpMemoryStore memoryStore) {
+ mService.complete(memoryStore);
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ });
+ }
+
+ /*
+ * If the IpMemoryStore is ready, this function will run the request synchronously.
+ * Otherwise, it will enqueue the requests for execution immediately after the
+ * service becomes ready. The requests are guaranteed to be executed in the order
+ * they are sumbitted.
+ */
+ @Override
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ mTailNode.getAndUpdate(future -> future.handle((store, exception) -> {
+ if (exception != null) {
+ // this should never happens since we also catch the exception below
+ Log.wtf(TAG, "Error fetching IpMemoryStore", exception);
+ return store;
+ }
+
+ try {
+ cb.accept(store);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception occurred: " + e.getMessage());
+ }
+ return store;
+ }));
+ }
+
+ @VisibleForTesting
+ protected ModuleNetworkStackClient getModuleNetworkStackClient(Context context) {
+ return ModuleNetworkStackClient.getInstance(context);
+ }
+
+ /** Gets an instance of the memory store */
+ @NonNull
+ public static IpMemoryStore getMemoryStore(final Context context) {
+ return new IpMemoryStore(context);
+ }
+}
diff --git a/common/networkstackclient/src/android/net/NetworkMonitorManager.java b/common/networkstackclient/src/android/net/NetworkMonitorManager.java
new file mode 100644
index 0000000..0f66981
--- /dev/null
+++ b/common/networkstackclient/src/android/net/NetworkMonitorManager.java
@@ -0,0 +1,203 @@
+/*
+ * 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.Hide;
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for INetworkMonitor.
+ *
+ * Wraps INetworkMonitor calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on INetworkMonitor are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+@Hide
+public class NetworkMonitorManager {
+
+ @NonNull private final INetworkMonitor mNetworkMonitor;
+ @NonNull private final String mTag;
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager,
+ @NonNull String tag) {
+ mNetworkMonitor = networkMonitorManager;
+ mTag = tag;
+ }
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager) {
+ this(networkMonitorManager, NetworkMonitorManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ // CHECKSTYLE:OFF Generated code
+
+ public boolean start() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.start();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in start", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean launchCaptivePortalApp() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.launchCaptivePortalApp();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in launchCaptivePortalApp", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyCaptivePortalAppFinished(int response) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyCaptivePortalAppFinished(response);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyCaptivePortalAppFinished", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean setAcceptPartialConnectivity() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.setAcceptPartialConnectivity();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in setAcceptPartialConnectivity", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean forceReevaluation(int uid) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.forceReevaluation(uid);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in forceReevaluation", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyPrivateDnsChanged(config);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyPrivateDnsChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyDnsResponse(int returnCode) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyDnsResponse(returnCode);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyDnsResponse", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkConnected(lp, nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkConnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkDisconnected() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkDisconnected();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkDisconnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyLinkPropertiesChanged(LinkProperties lp) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyLinkPropertiesChanged(lp);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyLinkPropertiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkCapabilitiesChanged(nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkCapabilitiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // CHECKSTYLE:ON Generated code
+}
diff --git a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
index 0aeebcb..54a5729 100644
--- a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
+++ b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
@@ -29,7 +29,9 @@
@JavaDerive(toString=true)
parcelable ProvisioningConfigurationParcelable {
+ /** @deprecated use ipv4ProvisioningMode instead. */
boolean enableIPv4;
+ /** @deprecated use ipv6ProvisioningMode instead. */
boolean enableIPv6;
boolean usingMultinetworkPolicyTracker;
boolean usingIpReachabilityMonitor;
@@ -45,4 +47,6 @@
@nullable ScanResultInfoParcelable scanResultInfo;
@nullable Layer2InformationParcelable layer2Info;
@nullable List<DhcpOption> options;
+ int ipv4ProvisioningMode;
+ int ipv6ProvisioningMode;
}
diff --git a/common/networkstackclient/src/android/net/ip/IIpClient.aidl b/common/networkstackclient/src/android/net/ip/IIpClient.aidl
index 029bdb3..f76a230 100644
--- a/common/networkstackclient/src/android/net/ip/IIpClient.aidl
+++ b/common/networkstackclient/src/android/net/ip/IIpClient.aidl
@@ -23,6 +23,36 @@
/** @hide */
oneway interface IIpClient {
+ /**
+ * Disable IPv4 provisioning.
+ */
+ const int PROV_IPV4_DISABLED = 0x00;
+
+ /**
+ * Enable IPv4 provisioning using static IP addresses.
+ */
+ const int PROV_IPV4_STATIC = 0x01;
+
+ /**
+ * Enable IPv4 provisioning using DHCP.
+ */
+ const int PROV_IPV4_DHCP = 0x02;
+
+ /**
+ * Disable IPv6 provisioning.
+ */
+ const int PROV_IPV6_DISABLED = 0x00;
+
+ /**
+ * Enable IPv6 provisioning via SLAAC.
+ */
+ const int PROV_IPV6_SLAAC = 0x01;
+
+ /**
+ * Enable IPv6 Link-local only.
+ */
+ const int PROV_IPV6_LINKLOCAL = 0x02;
+
void completedPreDhcpAction();
void confirmConfiguration();
void readPacketFilterComplete(in byte[] data);
diff --git a/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
new file mode 100644
index 0000000..b17fcaa
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
@@ -0,0 +1,136 @@
+/*
+ * 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.ip;
+
+import android.net.DhcpResultsParcelable;
+import android.net.Layer2PacketParcelable;
+import android.net.LinkProperties;
+
+import java.util.List;
+
+/**
+ * Callbacks for handling IpClient events.
+ *
+ * This is a convenience class to allow clients not to override all methods of IIpClientCallbacks,
+ * and avoid unparceling arguments.
+ * These methods are called asynchronously on a Binder thread, as IpClient lives in a different
+ * process.
+ * @hide
+ */
+public class IpClientCallbacks {
+
+ /**
+ * Callback called upon IpClient creation.
+ *
+ * @param ipClient The Binder token to communicate with IpClient.
+ */
+ public void onIpClientCreated(IIpClient ipClient) {}
+
+ /**
+ * Callback called prior to DHCP discovery/renewal.
+ *
+ * <p>In order to receive onPreDhcpAction(), call #withPreDhcpAction() when constructing a
+ * ProvisioningConfiguration.
+ *
+ * <p>Implementations of onPreDhcpAction() must call IpClient#completedPreDhcpAction() to
+ * indicate that DHCP is clear to proceed.
+ */
+ public void onPreDhcpAction() {}
+
+ /**
+ * Callback called after DHCP discovery/renewal.
+ */
+ public void onPostDhcpAction() {}
+
+ /**
+ * Callback called when new DHCP results are available.
+ *
+ * <p>This is purely advisory and not an indication of provisioning success or failure. This is
+ * only here for callers that want to expose DHCPv4 results to other APIs
+ * (e.g., WifiInfo#setInetAddress).
+ *
+ * <p>DHCPv4 or static IPv4 configuration failure or success can be determined by whether or not
+ * the passed-in DhcpResults object is null.
+ */
+ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
+ // In general callbacks would not use a parcelable directly (DhcpResultsParcelable), and
+ // would use a wrapper instead, because of the lack of safety of stable parcelables. But
+ // there are already two classes in the tree for DHCP information: DhcpInfo and DhcpResults,
+ // and neither of them exposes an appropriate API (they are bags of mutable fields and can't
+ // be changed because they are public API and @UnsupportedAppUsage, being no better than the
+ // stable parcelable). Adding a third class would cost more than the gain considering that
+ // the only client of this callback is WiFi, which will end up converting the results to
+ // DhcpInfo anyway.
+ }
+
+ /**
+ * Indicates that provisioning was successful.
+ */
+ public void onProvisioningSuccess(LinkProperties newLp) {}
+
+ /**
+ * Indicates that provisioning failed.
+ */
+ public void onProvisioningFailure(LinkProperties newLp) {}
+
+ /**
+ * Invoked on LinkProperties changes.
+ */
+ public void onLinkPropertiesChange(LinkProperties newLp) {}
+
+ /**Called when the internal IpReachabilityMonitor (if enabled) has
+ * detected the loss of a critical number of required neighbors.
+ */
+ public void onReachabilityLost(String logMsg) {}
+
+ /**
+ * Called when the IpClient state machine terminates.
+ */
+ public void onQuit() {}
+
+ /**
+ * Called to indicate that a new APF program must be installed to filter incoming packets.
+ */
+ public void installPacketFilter(byte[] filter) {}
+
+ /**
+ * Called to indicate that the APF Program & data buffer must be read asynchronously from the
+ * wifi driver.
+ *
+ * <p>Due to Wifi HAL limitations, the current implementation only supports dumping the entire
+ * buffer. In response to this request, the driver returns the data buffer asynchronously
+ * by sending an IpClient#EVENT_READ_PACKET_FILTER_COMPLETE message.
+ */
+ public void startReadPacketFilter() {}
+
+ /**
+ * If multicast filtering cannot be accomplished with APF, this function will be called to
+ * actuate multicast filtering using another means.
+ */
+ public void setFallbackMulticastFilter(boolean enabled) {}
+
+ /**
+ * Enabled/disable Neighbor Discover offload functionality. This is called, for example,
+ * whenever 464xlat is being started or stopped.
+ */
+ public void setNeighborDiscoveryOffload(boolean enable) {}
+
+ /**
+ * Invoked on starting preconnection process.
+ */
+ public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {}
+}
diff --git a/common/networkstackclient/src/android/net/ip/IpClientManager.java b/common/networkstackclient/src/android/net/ip/IpClientManager.java
new file mode 100644
index 0000000..b45405f
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientManager.java
@@ -0,0 +1,326 @@
+/*
+ * 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.ip;
+
+import android.annotation.Hide;
+import android.annotation.NonNull;
+import android.net.NattKeepalivePacketData;
+import android.net.ProxyInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.net.shared.Layer2Information;
+import android.net.shared.ProvisioningConfiguration;
+import android.net.util.KeepalivePacketDataUtil;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for IpClient.
+ *
+ * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+@Hide
+public class IpClientManager {
+ @NonNull private final IIpClient mIpClient;
+ @NonNull private final String mTag;
+
+ public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) {
+ mIpClient = ipClient;
+ mTag = tag;
+ }
+
+ public IpClientManager(@NonNull IIpClient ipClient) {
+ this(ipClient, IpClientManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ /**
+ * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be
+ * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to
+ * proceed.
+ */
+ public boolean completedPreDhcpAction() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.completedPreDhcpAction();
+ return true;
+ } catch (RemoteException e) {
+ log("Error completing PreDhcpAction", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Confirm the provisioning configuration.
+ */
+ public boolean confirmConfiguration() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.confirmConfiguration();
+ return true;
+ } catch (RemoteException e) {
+ log("Error confirming IpClient configuration", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Indicate that packet filter read is complete.
+ */
+ public boolean readPacketFilterComplete(byte[] data) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.readPacketFilterComplete(data);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient of packet filter read", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Shut down this IpClient instance altogether.
+ */
+ public boolean shutdown() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.shutdown();
+ return true;
+ } catch (RemoteException e) {
+ log("Error shutting down IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Start provisioning with the provided parameters.
+ */
+ public boolean startProvisioning(ProvisioningConfiguration prov) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.startProvisioning(prov.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error starting IpClient provisioning", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop this IpClient.
+ *
+ * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}.
+ */
+ public boolean stop() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.stop();
+ return true;
+ } catch (RemoteException e) {
+ log("Error stopping IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the TCP buffer sizes to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setTcpBufferSizes(String tcpBufferSizes) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setTcpBufferSizes(tcpBufferSizes);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient TCP buffer sizes", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the HTTP Proxy configuration to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setHttpProxy(ProxyInfo proxyInfo) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setHttpProxy(proxyInfo);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient proxy", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering,
+ * if not, Callback.setFallbackMulticastFilter() is called.
+ */
+ public boolean setMulticastFilter(boolean enabled) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setMulticastFilter(enabled);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting multicast filter", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+ return addKeepalivePacketFilter(slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ * @deprecated This method is for use on pre-S platforms where TcpKeepalivePacketData is not
+ * system API. On newer platforms use
+ * addKeepalivePacketFilter(int, TcpKeepalivePacketData) instead.
+ */
+ @Deprecated
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addKeepalivePacketFilter(slot, pkt);
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a NAT-T keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addNattKeepalivePacketFilter(
+ slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding NAT-T Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Remove a keepalive packet filter after stopping keepalive offload.
+ */
+ public boolean removeKeepalivePacketFilter(int slot) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.removeKeepalivePacketFilter(slot);
+ return true;
+ } catch (RemoteException e) {
+ log("Error removing Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the L2 key and group hint for storing info into the memory store.
+ */
+ public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setL2KeyAndGroupHint(l2Key, groupHint);
+ return true;
+ } catch (RemoteException e) {
+ log("Failed setL2KeyAndGroupHint", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Notify IpClient that preconnection is complete and that the link is ready for use.
+ * The success parameter indicates whether the packets passed in by 'onPreconnectionStart'
+ * were successfully sent to the network or not.
+ */
+ public boolean notifyPreconnectionComplete(boolean success) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.notifyPreconnectionComplete(success);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient Preconnection completed", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Update the bssid, L2 key and group hint layer2 information.
+ */
+ public boolean updateLayer2Information(Layer2Information info) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.updateLayer2Information(info.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error updating layer2 information", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ip/IpClientUtil.java b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
new file mode 100644
index 0000000..1b55776
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
@@ -0,0 +1,204 @@
+/*
+ * 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.ip;
+
+import android.content.Context;
+import android.net.DhcpResultsParcelable;
+import android.net.Layer2PacketParcelable;
+import android.net.LinkProperties;
+import android.net.networkstack.ModuleNetworkStackClient;
+import android.os.ConditionVariable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+
+/**
+ * Utilities and wrappers to simplify communication with IpClient, which lives in the NetworkStack
+ * process.
+ *
+ * @hide
+ */
+public class IpClientUtil {
+ // TODO: remove with its callers
+ public static final String DUMP_ARG = "ipclient";
+
+ /**
+ * Subclass of {@link IpClientCallbacks} allowing clients to block until provisioning is
+ * complete with {@link WaitForProvisioningCallbacks#waitForProvisioning()}.
+ */
+ public static class WaitForProvisioningCallbacks extends IpClientCallbacks {
+ private final ConditionVariable mCV = new ConditionVariable();
+ private LinkProperties mCallbackLinkProperties;
+
+ /**
+ * Block until either {@link #onProvisioningSuccess(LinkProperties)} or
+ * {@link #onProvisioningFailure(LinkProperties)} is called.
+ */
+ public LinkProperties waitForProvisioning() {
+ mCV.block();
+ return mCallbackLinkProperties;
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ mCallbackLinkProperties = newLp;
+ mCV.open();
+ }
+
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ mCallbackLinkProperties = null;
+ mCV.open();
+ }
+ }
+
+ /**
+ * Create a new IpClient.
+ *
+ * <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of
+ * {@link IIpClientCallbacks}.
+ * @see {@link ModuleNetworkStackClient#makeIpClient(String, IIpClientCallbacks)}
+ */
+ public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) {
+ ModuleNetworkStackClient.getInstance(context)
+ .makeIpClient(ifName, new IpClientCallbacksProxy(callback));
+ }
+
+ /**
+ * Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}.
+ */
+ private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
+ protected final IpClientCallbacks mCb;
+
+ /**
+ * Create a new IpClientCallbacksProxy.
+ */
+ IpClientCallbacksProxy(IpClientCallbacks cb) {
+ mCb = cb;
+ }
+
+ @Override
+ public void onIpClientCreated(IIpClient ipClient) {
+ mCb.onIpClientCreated(ipClient);
+ }
+
+ @Override
+ public void onPreDhcpAction() {
+ mCb.onPreDhcpAction();
+ }
+
+ @Override
+ public void onPostDhcpAction() {
+ mCb.onPostDhcpAction();
+ }
+
+ // This is purely advisory and not an indication of provisioning
+ // success or failure. This is only here for callers that want to
+ // expose DHCPv4 results to other APIs (e.g., WifiInfo#setInetAddress).
+ // DHCPv4 or static IPv4 configuration failure or success can be
+ // determined by whether or not the passed-in DhcpResults object is
+ // null or not.
+ @Override
+ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
+ mCb.onNewDhcpResults(dhcpResults);
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ mCb.onProvisioningSuccess(newLp);
+ }
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ mCb.onProvisioningFailure(newLp);
+ }
+
+ // Invoked on LinkProperties changes.
+ @Override
+ public void onLinkPropertiesChange(LinkProperties newLp) {
+ mCb.onLinkPropertiesChange(newLp);
+ }
+
+ // Called when the internal IpReachabilityMonitor (if enabled) has
+ // detected the loss of a critical number of required neighbors.
+ @Override
+ public void onReachabilityLost(String logMsg) {
+ mCb.onReachabilityLost(logMsg);
+ }
+
+ // Called when the IpClient state machine terminates.
+ @Override
+ public void onQuit() {
+ mCb.onQuit();
+ }
+
+ // Install an APF program to filter incoming packets.
+ @Override
+ public void installPacketFilter(byte[] filter) {
+ mCb.installPacketFilter(filter);
+ }
+
+ // Asynchronously read back the APF program & data buffer from the wifi driver.
+ // Due to Wifi HAL limitations, the current implementation only supports dumping the entire
+ // buffer. In response to this request, the driver returns the data buffer asynchronously
+ // by sending an IpClient#EVENT_READ_PACKET_FILTER_COMPLETE message.
+ @Override
+ public void startReadPacketFilter() {
+ mCb.startReadPacketFilter();
+ }
+
+ // If multicast filtering cannot be accomplished with APF, this function will be called to
+ // actuate multicast filtering using another means.
+ @Override
+ public void setFallbackMulticastFilter(boolean enabled) {
+ mCb.setFallbackMulticastFilter(enabled);
+ }
+
+ // Enabled/disable Neighbor Discover offload functionality. This is
+ // called, for example, whenever 464xlat is being started or stopped.
+ @Override
+ public void setNeighborDiscoveryOffload(boolean enable) {
+ mCb.setNeighborDiscoveryOffload(enable);
+ }
+
+ // Invoked on starting preconnection process.
+ @Override
+ public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
+ mCb.onPreconnectionStart(packets);
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ }
+
+ /**
+ * Dump logs for the specified IpClient.
+ * TODO: remove callers and delete
+ */
+ public static void dumpIpClient(
+ IIpClient connector, FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("IpClient logs have moved to dumpsys network_stack");
+ }
+}
diff --git a/common/moduleutils/src/android/net/shared/InitialConfiguration.java b/common/networkstackclient/src/android/net/shared/InitialConfiguration.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/InitialConfiguration.java
rename to common/networkstackclient/src/android/net/shared/InitialConfiguration.java
diff --git a/common/moduleutils/src/android/net/shared/Layer2Information.java b/common/networkstackclient/src/android/net/shared/Layer2Information.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/Layer2Information.java
rename to common/networkstackclient/src/android/net/shared/Layer2Information.java
diff --git a/common/moduleutils/src/android/net/shared/ParcelableUtil.java b/common/networkstackclient/src/android/net/shared/ParcelableUtil.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/ParcelableUtil.java
rename to common/networkstackclient/src/android/net/shared/ParcelableUtil.java
diff --git a/common/moduleutils/src/android/net/shared/PrivateDnsConfig.java b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/PrivateDnsConfig.java
rename to common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
diff --git a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java b/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
similarity index 81%
rename from common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
rename to common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
index d3bc04d..3bf6744 100644
--- a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
+++ b/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
@@ -16,12 +16,17 @@
package android.net.shared;
+import static android.net.ip.IIpClient.PROV_IPV4_DHCP;
+import static android.net.ip.IIpClient.PROV_IPV4_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV4_STATIC;
+import static android.net.ip.IIpClient.PROV_IPV6_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV6_LINKLOCAL;
+import static android.net.ip.IIpClient.PROV_IPV6_SLAAC;
import static android.net.shared.ParcelableUtil.fromParcelableArray;
import static android.net.shared.ParcelableUtil.toParcelableArray;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.INetd;
import android.net.InformationElementParcelable;
import android.net.Network;
import android.net.ProvisioningConfigurationParcelable;
@@ -32,6 +37,8 @@
import android.net.networkstack.aidl.dhcp.DhcpOption;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -76,6 +83,17 @@
// allowing for 10% jitter.
private static final int DEFAULT_TIMEOUT_MS = 18 * 1000;
+ // TODO: These cannot be imported from INetd.aidl, because networkstack-client cannot depend on
+ // INetd, as there are users of IpClient that depend on INetd directly (potentially at a
+ // different version, which is not allowed by the build system).
+ // Find a better way to express these constants.
+ public static final int IPV6_ADDR_GEN_MODE_EUI64 = 0;
+ public static final int IPV6_ADDR_GEN_MODE_STABLE_PRIVACY = 2;
+
+ // ipv4ProvisioningMode and ipv6ProvisioningMode members are introduced since
+ // networkstack-aidl-interfaces-v12.
+ public static final int VERSION_ADDED_PROVISIONING_ENUM = 12;
+
/**
* Builder to create a {@link ProvisioningConfiguration}.
*/
@@ -86,7 +104,7 @@
* Specify that the configuration should not enable IPv4. It is enabled by default.
*/
public Builder withoutIPv4() {
- mConfig.mEnableIPv4 = false;
+ mConfig.mIPv4ProvisioningMode = PROV_IPV4_DISABLED;
return this;
}
@@ -94,7 +112,7 @@
* Specify that the configuration should not enable IPv6. It is enabled by default.
*/
public Builder withoutIPv6() {
- mConfig.mEnableIPv6 = false;
+ mConfig.mIPv6ProvisioningMode = PROV_IPV6_DISABLED;
return this;
}
@@ -156,6 +174,7 @@
* Specify a static configuration for provisioning.
*/
public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
+ mConfig.mIPv4ProvisioningMode = PROV_IPV4_STATIC;
mConfig.mStaticIpConfig = staticConfig;
return this;
}
@@ -180,7 +199,7 @@
* Specify that IPv6 address generation should use a random MAC address.
*/
public Builder withRandomMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
+ mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_EUI64;
return this;
}
@@ -188,7 +207,7 @@
* Specify that IPv6 address generation should use a stable MAC address.
*/
public Builder withStableMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
return this;
}
@@ -233,15 +252,32 @@
*
* @param: options customized DHCP option stable parcelable list.
*/
- public Builder withDhcpOptions(List<DhcpOption> options) {
+ public Builder withDhcpOptions(@Nullable List<DhcpOption> options) {
mConfig.mDhcpOptions = options;
return this;
}
/**
+ * Specify that the configuration should enable IPv6 link-local only mode used for
+ * WiFi Neighbor Aware Networking and other link-local-only technologies. It's not
+ * used by default, and IPv4 must be disabled when this mode is enabled.
+ *
+ * @note This API is only supported since Android T.
+ */
+ public Builder withIpv6LinkLocalOnly() {
+ mConfig.mIPv6ProvisioningMode = PROV_IPV6_LINKLOCAL;
+ return this;
+ }
+
+ /**
* Build the configuration using previously specified parameters.
*/
public ProvisioningConfiguration build() {
+ if (mConfig.mIPv6ProvisioningMode == PROV_IPV6_LINKLOCAL
+ && mConfig.mIPv4ProvisioningMode != PROV_IPV4_DISABLED) {
+ throw new IllegalArgumentException("IPv4 must be disabled in IPv6 link-local"
+ + "only mode.");
+ }
return new ProvisioningConfiguration(mConfig);
}
}
@@ -427,8 +463,6 @@
}
}
- public boolean mEnableIPv4 = true;
- public boolean mEnableIPv6 = true;
public boolean mEnablePreconnection = false;
public boolean mUsingMultinetworkPolicyTracker = true;
public boolean mUsingIpReachabilityMonitor = true;
@@ -437,18 +471,18 @@
public StaticIpConfiguration mStaticIpConfig;
public ApfCapabilities mApfCapabilities;
public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
- public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ public int mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
public Network mNetwork = null;
public String mDisplayName = null;
public ScanResultInfo mScanResultInfo;
public Layer2Information mLayer2Info;
public List<DhcpOption> mDhcpOptions;
+ public int mIPv4ProvisioningMode = PROV_IPV4_DHCP;
+ public int mIPv6ProvisioningMode = PROV_IPV6_SLAAC;
public ProvisioningConfiguration() {} // used by Builder
public ProvisioningConfiguration(ProvisioningConfiguration other) {
- mEnableIPv4 = other.mEnableIPv4;
- mEnableIPv6 = other.mEnableIPv6;
mEnablePreconnection = other.mEnablePreconnection;
mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker;
mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
@@ -465,6 +499,8 @@
mScanResultInfo = other.mScanResultInfo;
mLayer2Info = other.mLayer2Info;
mDhcpOptions = other.mDhcpOptions;
+ mIPv4ProvisioningMode = other.mIPv4ProvisioningMode;
+ mIPv6ProvisioningMode = other.mIPv6ProvisioningMode;
}
/**
@@ -472,8 +508,10 @@
*/
public ProvisioningConfigurationParcelable toStableParcelable() {
final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
- p.enableIPv4 = mEnableIPv4;
- p.enableIPv6 = mEnableIPv6;
+ p.enableIPv4 = (mIPv4ProvisioningMode != PROV_IPV4_DISABLED);
+ p.ipv4ProvisioningMode = mIPv4ProvisioningMode;
+ p.enableIPv6 = (mIPv6ProvisioningMode != PROV_IPV6_DISABLED);
+ p.ipv6ProvisioningMode = mIPv6ProvisioningMode;
p.enablePreconnection = mEnablePreconnection;
p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker;
p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor;
@@ -495,13 +533,16 @@
/**
* Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable.
+ *
+ * @param p stable parcelable instance to be converted to a {@link ProvisioningConfiguration}.
+ * @param interfaceVersion IIpClientCallbacks interface version called by the remote peer,
+ * which is used to determine the appropriate parcelable members for
+ * backwards compatibility.
*/
public static ProvisioningConfiguration fromStableParcelable(
- @Nullable ProvisioningConfigurationParcelable p) {
+ @Nullable ProvisioningConfigurationParcelable p, int interfaceVersion) {
if (p == null) return null;
final ProvisioningConfiguration config = new ProvisioningConfiguration();
- config.mEnableIPv4 = p.enableIPv4;
- config.mEnableIPv6 = p.enableIPv6;
config.mEnablePreconnection = p.enablePreconnection;
config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker;
config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor;
@@ -518,14 +559,49 @@
config.mScanResultInfo = ScanResultInfo.fromStableParcelable(p.scanResultInfo);
config.mLayer2Info = Layer2Information.fromStableParcelable(p.layer2Info);
config.mDhcpOptions = (p.options == null) ? null : new ArrayList<>(p.options);
+ if (interfaceVersion < VERSION_ADDED_PROVISIONING_ENUM) {
+ config.mIPv4ProvisioningMode = p.enableIPv4 ? PROV_IPV4_DHCP : PROV_IPV4_DISABLED;
+ config.mIPv6ProvisioningMode = p.enableIPv6 ? PROV_IPV6_SLAAC : PROV_IPV6_DISABLED;
+ } else {
+ config.mIPv4ProvisioningMode = p.ipv4ProvisioningMode;
+ config.mIPv6ProvisioningMode = p.ipv6ProvisioningMode;
+ }
return config;
}
+ @VisibleForTesting
+ static String ipv4ProvisioningModeToString(int mode) {
+ switch (mode) {
+ case PROV_IPV4_DISABLED:
+ return "disabled";
+ case PROV_IPV4_STATIC:
+ return "static";
+ case PROV_IPV4_DHCP:
+ return "dhcp";
+ default:
+ return "unknown";
+ }
+ }
+
+ @VisibleForTesting
+ static String ipv6ProvisioningModeToString(int mode) {
+ switch (mode) {
+ case PROV_IPV6_DISABLED:
+ return "disabled";
+ case PROV_IPV6_SLAAC:
+ return "slaac";
+ case PROV_IPV6_LINKLOCAL:
+ return "link-local";
+ default:
+ return "unknown";
+ }
+ }
+
@Override
public String toString() {
+ final String ipv4ProvisioningMode = ipv4ProvisioningModeToString(mIPv4ProvisioningMode);
+ final String ipv6ProvisioningMode = ipv6ProvisioningModeToString(mIPv6ProvisioningMode);
return new StringJoiner(", ", getClass().getSimpleName() + "{", "}")
- .add("mEnableIPv4: " + mEnableIPv4)
- .add("mEnableIPv6: " + mEnableIPv6)
.add("mEnablePreconnection: " + mEnablePreconnection)
.add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker)
.add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor)
@@ -540,6 +616,8 @@
.add("mScanResultInfo: " + mScanResultInfo)
.add("mLayer2Info: " + mLayer2Info)
.add("mDhcpOptions: " + mDhcpOptions)
+ .add("mIPv4ProvisioningMode: " + ipv4ProvisioningMode)
+ .add("mIPv6ProvisioningMode: " + ipv6ProvisioningMode)
.toString();
}
@@ -569,9 +647,7 @@
public boolean equals(Object obj) {
if (!(obj instanceof ProvisioningConfiguration)) return false;
final ProvisioningConfiguration other = (ProvisioningConfiguration) obj;
- return mEnableIPv4 == other.mEnableIPv4
- && mEnableIPv6 == other.mEnableIPv6
- && mEnablePreconnection == other.mEnablePreconnection
+ return mEnablePreconnection == other.mEnablePreconnection
&& mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker
&& mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor
&& mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs
@@ -584,7 +660,9 @@
&& Objects.equals(mDisplayName, other.mDisplayName)
&& Objects.equals(mScanResultInfo, other.mScanResultInfo)
&& Objects.equals(mLayer2Info, other.mLayer2Info)
- && dhcpOptionListEquals(mDhcpOptions, other.mDhcpOptions);
+ && dhcpOptionListEquals(mDhcpOptions, other.mDhcpOptions)
+ && mIPv4ProvisioningMode == other.mIPv4ProvisioningMode
+ && mIPv6ProvisioningMode == other.mIPv6ProvisioningMode;
}
public boolean isValid() {
diff --git a/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java b/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
new file mode 100644
index 0000000..5666985
--- /dev/null
+++ b/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
@@ -0,0 +1,223 @@
+/*
+ * 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.util;
+
+import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.InvalidPacketException;
+import android.net.KeepalivePacketData;
+import android.net.NattKeepalivePacketData;
+import android.net.NattKeepalivePacketDataParcelable;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.os.Build;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.IpUtils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Utility class to convert to/from keepalive data parcelables.
+ *
+ * TODO: move to networkstack-client library when it is moved to frameworks/libs/net.
+ * This class cannot go into other shared libraries as it depends on NetworkStack AIDLs.
+ * @hide
+ */
+public final class KeepalivePacketDataUtil {
+ private static final int IPV4_HEADER_LENGTH = 20;
+ private static final int IPV6_HEADER_LENGTH = 40;
+ private static final int TCP_HEADER_LENGTH = 20;
+
+ private static final String TAG = KeepalivePacketDataUtil.class.getSimpleName();
+
+ /**
+ * Convert a NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public static NattKeepalivePacketDataParcelable toStableParcelable(
+ @NonNull NattKeepalivePacketData pkt) {
+ final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+ final InetAddress srcAddress = pkt.getSrcAddress();
+ final InetAddress dstAddress = pkt.getDstAddress();
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = pkt.getSrcPort();
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = pkt.getDstPort();
+ return parcel;
+ }
+
+ /**
+ * Convert a TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public static TcpKeepalivePacketDataParcelable toStableParcelable(
+ @NonNull TcpKeepalivePacketData pkt) {
+ final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+ final InetAddress srcAddress = pkt.getSrcAddress();
+ final InetAddress dstAddress = pkt.getDstAddress();
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = pkt.getSrcPort();
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = pkt.getDstPort();
+ parcel.seq = pkt.getTcpSeq();
+ parcel.ack = pkt.getTcpAck();
+ parcel.rcvWnd = pkt.getTcpWindow();
+ parcel.rcvWndScale = pkt.getTcpWindowScale();
+ parcel.tos = pkt.getIpTos();
+ parcel.ttl = pkt.getIpTtl();
+ return parcel;
+ }
+
+ /**
+ * Factory method to create tcp keepalive packet structure.
+ * @hide
+ */
+ public static TcpKeepalivePacketData fromStableParcelable(
+ TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
+ final byte[] packet;
+ try {
+ if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
+ && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
+ && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
+ packet = buildV4Packet(tcpDetails);
+ } else {
+ // TODO: support ipv6
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+ return new TcpKeepalivePacketData(
+ InetAddress.getByAddress(tcpDetails.srcAddress),
+ tcpDetails.srcPort,
+ InetAddress.getByAddress(tcpDetails.dstAddress),
+ tcpDetails.dstPort,
+ packet,
+ tcpDetails.seq, tcpDetails.ack, tcpDetails.rcvWnd, tcpDetails.rcvWndScale,
+ tcpDetails.tos, tcpDetails.ttl);
+ } catch (UnknownHostException e) {
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+
+ }
+
+ /**
+ * Build ipv4 tcp keepalive packet, not including the link-layer header.
+ */
+ // TODO : if this code is ever moved to the network stack, factorize constants with the ones
+ // over there.
+ private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
+ final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
+ ByteBuffer buf = ByteBuffer.allocate(length);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ buf.put((byte) 0x45); // IP version and IHL
+ buf.put((byte) tcpDetails.tos); // TOS
+ buf.putShort((short) length);
+ buf.putInt(0x00004000); // ID, flags=DF, offset
+ buf.put((byte) tcpDetails.ttl); // TTL
+ buf.put((byte) OsConstants.IPPROTO_TCP);
+ final int ipChecksumOffset = buf.position();
+ buf.putShort((short) 0); // IP checksum
+ buf.put(tcpDetails.srcAddress);
+ buf.put(tcpDetails.dstAddress);
+ buf.putShort((short) tcpDetails.srcPort);
+ buf.putShort((short) tcpDetails.dstPort);
+ buf.putInt(tcpDetails.seq); // Sequence Number
+ buf.putInt(tcpDetails.ack); // ACK
+ buf.putShort((short) 0x5010); // TCP length=5, flags=ACK
+ buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size
+ final int tcpChecksumOffset = buf.position();
+ buf.putShort((short) 0); // TCP checksum
+ // URG is not set therefore the urgent pointer is zero.
+ buf.putShort((short) 0); // Urgent pointer
+
+ buf.putShort(ipChecksumOffset, com.android.net.module.util.IpUtils.ipChecksum(buf, 0));
+ buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
+ buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
+
+ return buf.array();
+ }
+
+ // TODO: add buildV6Packet.
+
+ /**
+ * Get a {@link TcpKeepalivePacketDataParcelable} from {@link KeepalivePacketData}, if the
+ * generic class actually contains TCP keepalive data.
+ *
+ * @deprecated This method is used on R platforms where android.net.TcpKeepalivePacketData was
+ * not yet system API. Newer platforms should use android.net.TcpKeepalivePacketData directly.
+ *
+ * @param data A {@link KeepalivePacketData} that may contain TCP keepalive data.
+ * @return A parcelable containing TCP keepalive data, or null if the input data does not
+ * contain TCP keepalive data.
+ */
+ @Deprecated
+ @SuppressWarnings("AndroidFrameworkCompatChange") // API version check used to Log.wtf
+ @Nullable
+ public static TcpKeepalivePacketDataParcelable parseTcpKeepalivePacketData(
+ @Nullable KeepalivePacketData data) {
+ if (data == null) return null;
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+ Log.wtf(TAG, "parseTcpKeepalivePacketData should not be used after R, use "
+ + "TcpKeepalivePacketData instead.");
+ }
+
+ // Reconstruct TcpKeepalivePacketData from the packet contained in KeepalivePacketData
+ final ByteBuffer buffer = ByteBuffer.wrap(data.getPacket());
+ buffer.order(ByteOrder.BIG_ENDIAN);
+
+ // Most of the fields are accessible from the KeepalivePacketData superclass: instead of
+ // using Struct to parse everything, just extract the extra fields necessary for
+ // TcpKeepalivePacketData.
+ final int tcpSeq;
+ final int tcpAck;
+ final int wndSize;
+ final int ipTos;
+ final int ttl;
+ try {
+ // This only support IPv4, because TcpKeepalivePacketData only supports IPv4 for R and
+ // below, and this method should not be used on newer platforms.
+ tcpSeq = buffer.getInt(IPV4_HEADER_LENGTH + 4);
+ tcpAck = buffer.getInt(IPV4_HEADER_LENGTH + 8);
+ wndSize = buffer.getShort(IPV4_HEADER_LENGTH + 14);
+ ipTos = buffer.get(1);
+ ttl = buffer.get(8);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+
+ final TcpKeepalivePacketDataParcelable p = new TcpKeepalivePacketDataParcelable();
+ p.srcAddress = data.getSrcAddress().getAddress();
+ p.srcPort = data.getSrcPort();
+ p.dstAddress = data.getDstAddress().getAddress();
+ p.dstPort = data.getDstPort();
+ p.seq = tcpSeq;
+ p.ack = tcpAck;
+ // TcpKeepalivePacketData could actually use non-zero wndScale, but this does not affect
+ // actual functionality as generated packets will be the same (no wndScale option added)
+ p.rcvWnd = wndSize;
+ p.rcvWndScale = 0;
+ p.tos = ipTos;
+ p.ttl = ttl;
+ return p;
+ }
+}
diff --git a/jarjar-rules-shared.txt b/jarjar-rules-shared.txt
index bb2acd4..e8c9c19 100644
--- a/jarjar-rules-shared.txt
+++ b/jarjar-rules-shared.txt
@@ -11,3 +11,6 @@
rule android.util.LocalLog* android.net.networkstack.util.LocalLog@1
rule android.util.IndentingPrintWriter* android.net.networkstack.util.AndroidUtilIndentingPrintWriter@1
+
+# Classes from modules-utils-build_system
+rule com.android.modules.utils.build.** com.android.networkstack.utils.build.@1
\ No newline at end of file
diff --git a/lint-baseline-api-30-shims.xml b/lint-baseline-api-30-shims.xml
new file mode 100644
index 0000000..da541cd
--- /dev/null
+++ b/lint-baseline-api-30-shims.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" return lp.getNat64Prefix();"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java"
+ line="85"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#setNat64Prefix`"
+ errorLine1=" lp.setNat64Prefix(prefix);"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java"
+ line="90"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#setDhcpServerAddress`"
+ errorLine1=" lp.setDhcpServerAddress(serverAddress);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/apishim/30/com/android/networkstack/apishim/api30/NetworkInformationShimImpl.java"
+ line="109"
+ column="12"/>
+ </issue>
+
+</issues>
diff --git a/lint-baseline-current-lib.xml b/lint-baseline-current-lib.xml
new file mode 100644
index 0000000..e8cfe3e
--- /dev/null
+++ b/lint-baseline-current-lib.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/android/net/ip/IpClient.java"
+ line="1337"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#setNat64Prefix`"
+ errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/android/net/ip/IpClient.java"
+ line="1337"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.telephony.NetworkRegistrationInfo#getCellIdentity`"
+ errorLine1=" nri == null ? null : nri.getCellIdentity());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+ line="3088"
+ column="46"/>
+ </issue>
+
+</issues>
diff --git a/lint-baseline-stable-lib.xml b/lint-baseline-stable-lib.xml
new file mode 100644
index 0000000..e8cfe3e
--- /dev/null
+++ b/lint-baseline-stable-lib.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/android/net/ip/IpClient.java"
+ line="1337"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#setNat64Prefix`"
+ errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/android/net/ip/IpClient.java"
+ line="1337"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.telephony.NetworkRegistrationInfo#getCellIdentity`"
+ errorLine1=" nri == null ? null : nri.getCellIdentity());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+ line="3088"
+ column="46"/>
+ </issue>
+
+</issues>
diff --git a/proguard.flags b/proguard.flags
index af4262a..7f8f207 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -8,6 +8,10 @@
static final int EVENT_*;
}
+-keepclassmembers public class * extends com.android.networkstack.util.Struct {
+ *;
+}
+
# The lite proto runtime uses reflection to access fields based on the names in
# the schema, keep all the fields.
# This replicates the base proguard rule used by the build by default
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index e54f11c..706f174 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -19,7 +19,7 @@
<string name="notification_channel_name_connected" msgid="1795068343200033922">"Godkendelse til loginportal"</string>
<string name="notification_channel_description_connected" msgid="7239184168268014518">"De notifikationer, der vises, når enheden er blevet godkendt til et netværk via en loginportal"</string>
<string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"Oplysninger om netværksplacering"</string>
- <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Notifikationer, der vises for at indikere, at netværket har en side med oplysninger om placeringen"</string>
+ <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Notifikationer, der vises for at indikere, at netværket har en side med oplysninger om lokationen"</string>
<string name="connected" msgid="4563643884927480998">"Der er oprettet forbindelse"</string>
<string name="tap_for_info" msgid="6849746325626883711">"Der er oprettet forbindelse/tryk for at se website"</string>
<string name="application_label" msgid="1322847171305285454">"Netværksadministrator"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 4772691..2267cd4 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -18,9 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_name_connected" msgid="1795068343200033922">"אימות של פורטל שבוי"</string>
<string name="notification_channel_description_connected" msgid="7239184168268014518">"התראות המוצגות כשהמכשיר אומת בהצלחה וחובר לרשת של פורטל שבוי"</string>
- <string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"מידע על מקום רשת"</string>
+ <string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"מידע על מקום הרשת"</string>
<string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"התראות המוצגות כדי לציין שלרשת יש דף מידע על מקום"</string>
- <string name="connected" msgid="4563643884927480998">"מחובר"</string>
+ <string name="connected" msgid="4563643884927480998">"המכשיר מחובר"</string>
<string name="tap_for_info" msgid="6849746325626883711">"מחוברת / יש להקיש כדי להציג את האתר"</string>
<string name="application_label" msgid="1322847171305285454">"ניהול רשתות"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 9aec881..bed0ea7 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -17,9 +17,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_name_connected" msgid="1795068343200033922">"Кирүү бетинин аутентификациясы"</string>
- <string name="notification_channel_description_connected" msgid="7239184168268014518">"Түзмөк тармактын кирүү бети аркылуу аутентификациядан ийгиликтүү өткөндө билдирмелер көрсөтүлөт"</string>
+ <string name="notification_channel_description_connected" msgid="7239184168268014518">"Түзмөк тармактын кирүү бети аркылуу аутентификациядан ийгиликтүү өткөндө билдирмелер көрүнөт"</string>
<string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"Тармактын жайгашуусу жөнүндө маалымат"</string>
- <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Тармак маалымат барагына киргенде билдирме көрсөтүлөт"</string>
+ <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Тармак маалымат барагына киргенде билдирме көрүнөт"</string>
<string name="connected" msgid="4563643884927480998">"Туташты"</string>
<string name="tap_for_info" msgid="6849746325626883711">"Туташты / Вебсайтты көрүү үчүн таптаңыз"</string>
<string name="application_label" msgid="1322847171305285454">"Тармактарды башкаргыч"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 500d584..b7ff1bc 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -20,7 +20,7 @@
<string name="notification_channel_description_connected" msgid="7239184168268014518">"यन्त्र क्याप्टिभ पोर्टल नेटवर्कमा सफलतापूर्वक जोडिएको कुरा प्रमाणित भएपछि देखाइने सूचनाहरू"</string>
<string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"नेटवर्कको स्थानसम्बन्धी जानकारी"</string>
<string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"नेटवर्कको स्थानसम्बन्धी जानकारी भएको पृष्ठ रहेको सङ्केत गर्न देखाइने सूचनाहरू"</string>
- <string name="connected" msgid="4563643884927480998">"जोडिएको छ"</string>
+ <string name="connected" msgid="4563643884927480998">"कनेक्ट गरिएको छ"</string>
<string name="tap_for_info" msgid="6849746325626883711">"जोडियो / वेबसाइट हेर्न ट्याप गर्नुहोस्"</string>
<string name="application_label" msgid="1322847171305285454">"नेटवर्क व्यवस्थापक"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 527d895..7b54302 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -17,9 +17,9 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="notification_channel_name_connected" msgid="1795068343200033922">"Verificatie van captive portal"</string>
- <string name="notification_channel_description_connected" msgid="7239184168268014518">"Er worden meldingen weergegeven als het apparaat is geverifieerd voor een captive portal-netwerk"</string>
+ <string name="notification_channel_description_connected" msgid="7239184168268014518">"Er worden meldingen getoond als het apparaat is geverifieerd voor een captive portal-netwerk"</string>
<string name="notification_channel_name_network_venue_info" msgid="6526543187249265733">"Netwerklocatie-informatie"</string>
- <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Er worden meldingen weergegeven om aan te geven dat het netwerk een locatie-informatiepagina heeft"</string>
+ <string name="notification_channel_description_network_venue_info" msgid="5131499595382733605">"Er worden meldingen getoond om aan te geven dat het netwerk een locatie-informatiepagina heeft"</string>
<string name="connected" msgid="4563643884927480998">"Verbonden"</string>
<string name="tap_for_info" msgid="6849746325626883711">"Verbonden / Tik om de website te bekijken"</string>
<string name="application_label" msgid="1322847171305285454">"Netwerkbeheer"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index d6a11ab..805ca04 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -105,4 +105,20 @@
increased until reaching the config_max_retry_timer. -->
<integer name="config_evaluating_bandwidth_min_retry_timer_ms"></integer>
<integer name="config_evaluating_bandwidth_max_retry_timer_ms"></integer>
+
+ <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
+ Those frames are identified by the field Eth-type having values
+ less than 0x600 -->
+ <bool name="config_apfDrop802_3Frames">true</bool>
+
+ <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
+ will be dropped
+ TODO: need to put proper values, these are for testing purposes only -->
+ <integer-array name="config_apfEthTypeDenyList">
+ <item>0x88A2</item>
+ <item>0x88A4</item>
+ <item>0x88B8</item>
+ <item>0x88CD</item>
+ <item>0x88E3</item>
+ </integer-array>
</resources>
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
index b2967b9..bfb450e 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -77,6 +77,13 @@
<item type="integer" name="config_evaluating_bandwidth_timeout_ms"/>
<item type="integer" name="config_evaluating_bandwidth_min_retry_timer_ms"/>
<item type="integer" name="config_evaluating_bandwidth_max_retry_timer_ms"/>
+
+ <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
+ Those frames are identified by the field Eth-type having values less than 0x600 -->
+ <item type="bool" name="config_apfDrop802_3Frames"/>
+ <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
+ will be dropped -->
+ <item type="array" name="config_apfEthTypeDenyList"/>
</policy>
</overlayable>
</resources>
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 0bb4094..7a13392 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -27,6 +27,7 @@
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_RAW;
+import static com.android.net.module.util.NetworkStackConstants.ETHER_BROADCAST;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
@@ -285,8 +286,6 @@
private static final int ETH_ETHERTYPE_OFFSET = 12;
private static final int ETH_TYPE_MIN = 0x0600;
private static final int ETH_TYPE_MAX = 0xFFFF;
- private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
- {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
// TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
private static final int IPV4_TOTAL_LENGTH_OFFSET = ETH_HEADER_LEN + 2;
private static final int IPV4_FRAGMENT_OFFSET_OFFSET = ETH_HEADER_LEN + 6;
@@ -1254,7 +1253,7 @@
// Pass if unicast reply.
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETHER_BROADCAST, mCountAndPassLabel);
// Either a unicast request, a unicast reply, or a broadcast reply.
gen.defineLabel(checkTargetIPv4);
@@ -1350,7 +1349,7 @@
// TODO: can we invert this condition to fall through to the common pass case below?
maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST);
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETHER_BROADCAST, mCountAndPassLabel);
maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST);
gen.addJump(mCountAndDropLabel);
} else {
@@ -1412,7 +1411,7 @@
// pass
// if it's ICMPv6 RS to any:
// drop
- // if it's ICMPv6 NA to ff02::1:
+ // if it's ICMPv6 NA to anything in ff02::/120
// drop
// if keepalive ack
// drop
@@ -1466,11 +1465,14 @@
gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, mCountAndDropLabel);
// If not neighbor announcements, skip filter.
gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel);
- // If to ff02::1, drop.
+ // Drop all multicast NA to ff02::/120.
+ // This is a way to cover ff02::1 and ff02::2 with a single JNEBS.
// TODO: Drop only if they don't contain the address of on-link neighbours.
+ final byte[] unsolicitedNaDropPrefix = Arrays.copyOf(IPV6_ALL_NODES_ADDRESS, 15);
gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
+ gen.addJumpIfBytesNotEqual(Register.R0, unsolicitedNaDropPrefix,
skipUnsolicitedMulticastNALabel);
+
maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA);
gen.addJump(mCountAndDropLabel);
gen.defineLabel(skipUnsolicitedMulticastNALabel);
@@ -1493,7 +1495,7 @@
* <li>Drop all broadcast non-IP non-ARP packets.
* <li>Pass all non-ICMPv6 IPv6 packets,
* <li>Pass all non-IPv4 and non-IPv6 packets,
- * <li>Drop IPv6 ICMPv6 NAs to ff02::1.
+ * <li>Drop IPv6 ICMPv6 NAs to anything in ff02::/120.
* <li>Drop IPv6 ICMPv6 RSs.
* <li>Filter IPv4 packets (see generateIPv4FilterLocked())
* <li>Filter IPv6 packets (see generateIPv6FilterLocked())
@@ -1569,7 +1571,7 @@
// Drop non-IP non-ARP broadcasts, pass the rest
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
maybeSetupCounter(gen, Counter.PASSED_NON_IP_UNICAST);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETHER_BROADCAST, mCountAndPassLabel);
maybeSetupCounter(gen, Counter.DROPPED_ETH_BROADCAST);
gen.addJump(mCountAndDropLabel);
diff --git a/src/android/net/apf/ApfGenerator.java b/src/android/net/apf/ApfGenerator.java
index 44ce2db..bf4d910 100644
--- a/src/android/net/apf/ApfGenerator.java
+++ b/src/android/net/apf/ApfGenerator.java
@@ -752,7 +752,8 @@
/**
* Add an instruction to the end of the program to jump to {@code target} if the bytes of the
- * packet at an offset specified by {@code register} match {@code bytes}.
+ * packet at an offset specified by {@code register} don't match {@code bytes}, {@code register}
+ * must be R0.
*/
public ApfGenerator addJumpIfBytesNotEqual(Register register, byte[] bytes, String target)
throws IllegalInstructionException {
diff --git a/src/android/net/dhcp/DhcpClient.java b/src/android/net/dhcp/DhcpClient.java
index 5f77128..8e0e9d3 100644
--- a/src/android/net/dhcp/DhcpClient.java
+++ b/src/android/net/dhcp/DhcpClient.java
@@ -97,9 +97,9 @@
import com.android.internal.util.MessageUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.internal.util.TrafficStatsConstants;
import com.android.internal.util.WakeupMessage;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.NetworkStackConstants;
import com.android.net.module.util.PacketReader;
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
@@ -611,7 +611,7 @@
private boolean initUdpSocket() {
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_DHCP);
+ NetworkStackConstants.TAG_SYSTEM_DHCP);
try {
mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
SocketUtils.bindSocketToInterface(mUdpSock, mIfaceName);
diff --git a/src/android/net/dhcp/DhcpPacket.java b/src/android/net/dhcp/DhcpPacket.java
index f70f3ec..76dc807 100644
--- a/src/android/net/dhcp/DhcpPacket.java
+++ b/src/android/net/dhcp/DhcpPacket.java
@@ -200,7 +200,8 @@
* DHCP Optional Type: DHCP Interface MTU
*/
public static final byte DHCP_MTU = 26;
- protected Short mMtu;
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ public Short mMtu;
/**
* DHCP Optional Type: DHCP BROADCAST ADDRESS
@@ -402,7 +403,7 @@
// Set in unit tests, to ensure that the test does not break when run on different devices and
// on different releases.
- static String testOverrideVendorId = null;
+ static String sTestOverrideVendorId = null;
protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
Inet4Address nextIp, Inet4Address relayIp,
@@ -778,7 +779,7 @@
* with the customized option value if any.
*/
private static String getVendorId(@Nullable List<DhcpOption> customizedClientOptions) {
- if (testOverrideVendorId != null) return testOverrideVendorId;
+ if (sTestOverrideVendorId != null) return sTestOverrideVendorId;
String vendorId = "android-dhcp-" + Build.VERSION.RELEASE;
if (customizedClientOptions != null) {
diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java
index 3acd76e..3465e72 100644
--- a/src/android/net/dhcp/DhcpServer.java
+++ b/src/android/net/dhcp/DhcpServer.java
@@ -33,12 +33,12 @@
import static android.system.OsConstants.SO_BROADCAST;
import static android.system.OsConstants.SO_REUSEADDR;
-import static com.android.internal.util.TrafficStatsConstants.TAG_SYSTEM_DHCP_SERVER;
import static com.android.net.module.util.Inet4AddressUtils.getBroadcastAddress;
import static com.android.net.module.util.Inet4AddressUtils.getPrefixMaskAsInet4Address;
import static com.android.net.module.util.NetworkStackConstants.INFINITE_LEASE;
import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ALL;
import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY;
+import static com.android.net.module.util.NetworkStackConstants.TAG_SYSTEM_DHCP_SERVER;
import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
import static java.lang.Integer.toUnsignedLong;
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index a73e997..12ab3fd 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -18,12 +18,28 @@
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.dhcp.DhcpResultsParcelableUtil.toStableParcelable;
+import static android.net.ip.IIpClient.PROV_IPV4_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV6_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV6_LINKLOCAL;
+import static android.net.util.NetworkStackUtils.IPCLIENT_DISABLE_ACCEPT_RA_VERSION;
+import static android.net.util.NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION;
+import static android.net.util.NetworkStackUtils.IPCLIENT_GRATUITOUS_NA_VERSION;
+import static android.net.util.SocketUtils.makePacketSocketAddress;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.system.OsConstants.AF_PACKET;
+import static android.system.OsConstants.ETH_P_ARP;
+import static android.system.OsConstants.ETH_P_IPV6;
+import static android.system.OsConstants.SOCK_NONBLOCK;
+import static android.system.OsConstants.SOCK_RAW;
+import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY;
+import static com.android.net.module.util.NetworkStackConstants.ETHER_BROADCAST;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.VENDOR_SPECIFIC_IE_ID;
import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
import android.content.Context;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.INetd;
@@ -48,19 +64,25 @@
import android.net.metrics.IpManagerEvent;
import android.net.networkstack.aidl.dhcp.DhcpOption;
import android.net.shared.InitialConfiguration;
+import android.net.shared.Layer2Information;
import android.net.shared.ProvisioningConfiguration;
import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.shared.ProvisioningConfiguration.ScanResultInfo.InformationElement;
import android.net.util.InterfaceParams;
+import android.net.util.NetworkStackUtils;
import android.net.util.SharedLog;
import android.os.Build;
import android.os.ConditionVariable;
+import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.stats.connectivity.DisconnectCode;
+import android.stats.connectivity.NetworkQuirkEvent;
+import android.system.ErrnoException;
+import android.system.Os;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -78,17 +100,26 @@
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.networkstack.R;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
+import com.android.networkstack.apishim.SocketUtilsShimImpl;
import com.android.networkstack.apishim.common.NetworkInformationShim;
import com.android.networkstack.apishim.common.ShimUtils;
+import com.android.networkstack.arp.ArpPacket;
import com.android.networkstack.metrics.IpProvisioningMetrics;
+import com.android.networkstack.metrics.NetworkQuirkMetrics;
+import com.android.networkstack.packets.NeighborAdvertisement;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.MalformedURLException;
+import java.net.SocketAddress;
+import java.net.SocketException;
import java.net.URL;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
@@ -121,6 +152,7 @@
* @hide
*/
public class IpClient extends StateMachine {
+ private static final String TAG = IpClient.class.getSimpleName();
private static final boolean DBG = false;
// For message logging.
@@ -134,6 +166,7 @@
private final NetworkStackIpMemoryStore mIpMemoryStore;
private final NetworkInformationShim mShim = NetworkInformationShimImpl.newInstance();
private final IpProvisioningMetrics mIpProvisioningMetrics = new IpProvisioningMetrics();
+ private final NetworkQuirkMetrics mNetworkQuirkMetrics;
/**
* Dump all state machine and connectivity packet logs to the specified writer.
@@ -367,6 +400,24 @@
log("Failed to call onPreconnectionStart", e);
}
}
+
+ /**
+ * Get the version of the IIpClientCallbacks AIDL interface.
+ */
+ public int getInterfaceVersion() {
+ log("getInterfaceVersion");
+ try {
+ return mCallback.getInterfaceVersion();
+ } catch (RemoteException e) {
+ // This can never happen for callers in the system server, because if the
+ // system server crashes, then the networkstack will crash as well. But it can
+ // happen for other callers such as bluetooth or telephony (if it starts to use
+ // IpClient). 0 will generally work but will assume an old client and disable
+ // all new features.
+ log("Failed to call getInterfaceVersion", e);
+ return 0;
+ }
+ }
}
public static final String DUMP_ARG_CONFIRM = "confirm";
@@ -479,6 +530,8 @@
private final MessageHandlingLogger mMsgStateLogger;
private final IpConnectivityLog mMetricsLog;
private final InterfaceController mInterfaceCtrl;
+ // Set of IPv6 addresses for which unsolicited gratuitous NA packets have been sent.
+ private final Set<Inet6Address> mGratuitousNaTargetAddresses = new HashSet<>();
// Ignore nonzero RDNSS option lifetimes below this value. 0 = disabled.
private final int mMinRdnssLifetimeSec;
@@ -501,7 +554,7 @@
private boolean mMulticastFiltering;
private long mStartTimeMillis;
private MacAddress mCurrentBssid;
- private boolean mHasDisabledIPv6OnProvLoss;
+ private boolean mHasDisabledIpv6OrAcceptRaOnProvLoss;
/**
* Reading the snapshot is an asynchronous operation initiated by invoking
@@ -564,6 +617,52 @@
public IpConnectivityLog getIpConnectivityLog() {
return new IpConnectivityLog();
}
+
+ /**
+ * Get a NetworkQuirkMetrics instance.
+ */
+ public NetworkQuirkMetrics getNetworkQuirkMetrics() {
+ return new NetworkQuirkMetrics();
+ }
+
+ /**
+ * Get a IpReachabilityMonitor instance.
+ */
+ public IpReachabilityMonitor getIpReachabilityMonitor(Context context,
+ InterfaceParams ifParams, Handler h, SharedLog log,
+ IpReachabilityMonitor.Callback callback, boolean usingMultinetworkPolicyTracker,
+ IpReachabilityMonitor.Dependencies deps, final INetd netd) {
+ return new IpReachabilityMonitor(context, ifParams, h, log, callback,
+ usingMultinetworkPolicyTracker, deps, netd);
+ }
+
+ /**
+ * Get a IpReachabilityMonitor dependencies instance.
+ */
+ public IpReachabilityMonitor.Dependencies getIpReachabilityMonitorDeps(Context context,
+ String name) {
+ return IpReachabilityMonitor.Dependencies.makeDefault(context, name);
+ }
+
+ /**
+ * Return whether a feature guarded by a feature flag is enabled.
+ * @see NetworkStackUtils#isFeatureEnabled(Context, String, String)
+ */
+ public boolean isFeatureEnabled(final Context context, final String name,
+ boolean defaultEnabled) {
+ return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
+ defaultEnabled);
+ }
+
+ /**
+ * Create an APF filter if apfCapabilities indicates support for packet filtering using
+ * APF programs.
+ * @see ApfFilter#maybeCreate
+ */
+ public ApfFilter maybeCreateApfFilter(Context context, ApfFilter.ApfConfiguration config,
+ InterfaceParams ifParams, IpClientCallbacksWrapper cb) {
+ return ApfFilter.maybeCreate(context, config, ifParams, cb);
+ }
}
public IpClient(Context context, String ifName, IIpClientCallbacks callback,
@@ -586,6 +685,7 @@
mClatInterfaceName = CLAT_PREFIX + ifName;
mDependencies = deps;
mMetricsLog = deps.getIpConnectivityLog();
+ mNetworkQuirkMetrics = deps.getNetworkQuirkMetrics();
mShutdownLatch = new CountDownLatch(1);
mCm = mContext.getSystemService(ConnectivityManager.class);
mObserverRegistry = observerRegistry;
@@ -615,7 +715,7 @@
(ifaceUp) -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED, ifaceUp
? ARG_LINKPROP_CHANGED_LINKSTATE_UP
: ARG_LINKPROP_CHANGED_LINKSTATE_DOWN),
- config, mLog) {
+ config, mLog, mDependencies) {
@Override
public void onInterfaceAdded(String iface) {
super.onInterfaceAdded(iface);
@@ -647,6 +747,21 @@
logMsg(msg);
}
+ @Override
+ public void onInterfaceAddressRemoved(LinkAddress address, String iface) {
+ super.onInterfaceAddressRemoved(address, iface);
+ if (!mInterfaceName.equals(iface)) return;
+ if (!address.isIpv6()) return;
+ final Inet6Address targetIp = (Inet6Address) address.getAddress();
+ if (mGratuitousNaTargetAddresses.contains(targetIp)) {
+ mGratuitousNaTargetAddresses.remove(targetIp);
+
+ final String msg = "Global IPv6 address: " + targetIp
+ + " has removed from the set of gratuitous NA target address.";
+ logMsg(msg);
+ }
+ }
+
private void logMsg(String msg) {
Log.d(mTag, msg);
getHandler().post(() -> mLog.log("OBSERVED " + msg));
@@ -701,7 +816,8 @@
@Override
public void startProvisioning(ProvisioningConfigurationParcelable req) {
enforceNetworkStackCallingPermission();
- IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req));
+ IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req,
+ mCallback.getInterfaceVersion()));
}
@Override
public void stop() {
@@ -790,9 +906,49 @@
private void stopStateMachineUpdaters() {
mObserverRegistry.unregisterObserver(mLinkObserver);
+ mLinkObserver.clearInterfaceParams();
mLinkObserver.shutdown();
}
+ private boolean isGratuitousNaEnabled() {
+ return mDependencies.isFeatureEnabled(mContext, IPCLIENT_GRATUITOUS_NA_VERSION,
+ false /* defaultEnabled */);
+ }
+
+ private boolean isGratuitousArpNaRoamingEnabled() {
+ return mDependencies.isFeatureEnabled(mContext, IPCLIENT_GARP_NA_ROAMING_VERSION,
+ false /* defaultEnabled */);
+ }
+
+ @VisibleForTesting
+ static MacAddress getInitialBssid(final Layer2Information layer2Info,
+ final ScanResultInfo scanResultInfo, boolean isAtLeastS) {
+ MacAddress bssid = null;
+ // http://b/185202634
+ // ScanResultInfo is not populated in some situations.
+ // On S and above, prefer getting the BSSID from the Layer2Info.
+ // On R and below, get the BSSID from the ScanResultInfo and fall back to
+ // getting it from the Layer2Info. This ensures no regressions if any R
+ // devices pass in a null or meaningless BSSID in the Layer2Info.
+ if (!isAtLeastS && scanResultInfo != null) {
+ try {
+ bssid = MacAddress.fromString(scanResultInfo.getBssid());
+ } catch (IllegalArgumentException e) {
+ Log.wtf(TAG, "Invalid BSSID: " + scanResultInfo.getBssid()
+ + " in provisioning configuration", e);
+ }
+ }
+ if (bssid == null && layer2Info != null) {
+ bssid = layer2Info.mBssid;
+ }
+ return bssid;
+ }
+
+ private boolean shouldDisableAcceptRaOnProvisioningLoss() {
+ return mDependencies.isFeatureEnabled(mContext, IPCLIENT_DISABLE_ACCEPT_RA_VERSION,
+ true /* defaultEnabled */);
+ }
+
@Override
protected void onQuitting() {
mCallback.onQuit();
@@ -816,17 +972,8 @@
return;
}
- final ScanResultInfo scanResultInfo = req.mScanResultInfo;
- mCurrentBssid = null;
- if (scanResultInfo != null) {
- try {
- mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());
- } catch (IllegalArgumentException e) {
- Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
- + " in provisioning configuration", e);
- }
- }
-
+ mCurrentBssid = getInitialBssid(req.mLayer2Info, req.mScanResultInfo,
+ ShimUtils.isAtLeastS());
if (req.mLayer2Info != null) {
mL2Key = req.mLayer2Info.mL2Key;
mCluster = req.mLayer2Info.mCluster;
@@ -1103,12 +1250,41 @@
transitionTo(mStoppingState);
}
+ private static boolean hasIpv6LinkLocalInterfaceRoute(final LinkProperties lp) {
+ for (RouteInfo r : lp.getRoutes()) {
+ if (r.getDestination().equals(new IpPrefix("fe80::/64"))
+ && r.getGateway().isAnyLocalAddress()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasIpv6LinkLocalAddress(final LinkProperties lp) {
+ for (LinkAddress address : lp.getLinkAddresses()) {
+ if (address.isIpv6() && address.getAddress().isLinkLocalAddress()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // LinkProperties has a link-local (fe80::xxx) IPv6 address and route to fe80::/64 destination.
+ private boolean isIpv6LinkLocalProvisioned(final LinkProperties lp) {
+ if (mConfiguration == null
+ || mConfiguration.mIPv6ProvisioningMode != PROV_IPV6_LINKLOCAL) return false;
+ if (hasIpv6LinkLocalAddress(lp) && hasIpv6LinkLocalInterfaceRoute(lp)) return true;
+ return false;
+ }
+
// For now: use WifiStateMachine's historical notion of provisioned.
@VisibleForTesting
- static boolean isProvisioned(LinkProperties lp, InitialConfiguration config) {
- // For historical reasons, we should connect even if all we have is
- // an IPv4 address and nothing else.
- if (lp.hasIpv4Address() || lp.isProvisioned()) {
+ boolean isProvisioned(final LinkProperties lp, final InitialConfiguration config) {
+ // For historical reasons, we should connect even if all we have is an IPv4
+ // address and nothing else. If IPv6 link-local only mode is enabled and
+ // it's provisioned without IPv4, then still connecting once IPv6 link-local
+ // address is ready to use and route to fe80::/64 destination is up.
+ if (lp.hasIpv4Address() || lp.isProvisioned() || isIpv6LinkLocalProvisioned(lp)) {
return true;
}
if (config == null) {
@@ -1120,6 +1296,21 @@
return config.isProvisionedBy(lp.getLinkAddresses(), lp.getRoutes());
}
+ private void setIpv6AcceptRa(int acceptRa) {
+ try {
+ mNetd.setProcSysNet(INetd.IPV6, INetd.CONF, mInterfaceParams.name, "accept_ra",
+ Integer.toString(acceptRa));
+ } catch (Exception e) {
+ Log.e(mTag, "Failed to set accept_ra to " + acceptRa);
+ }
+ }
+
+ private void restartIpv6WithAcceptRaDisabled() {
+ mInterfaceCtrl.disableIPv6();
+ setIpv6AcceptRa(0 /* accept_ra */);
+ startIPv6();
+ }
+
// TODO: Investigate folding all this into the existing static function
// LinkProperties.compareProvisioning() or some other single function that
// takes two LinkProperties objects and returns a ProvisioningChange
@@ -1169,7 +1360,7 @@
// Note that we can still be disconnected by IpReachabilityMonitor
// if the IPv6 default gateway (but not the IPv6 DNS servers; see
// accompanying code in IpReachabilityMonitor) is unreachable.
- final boolean ignoreIPv6ProvisioningLoss = mHasDisabledIPv6OnProvLoss
+ final boolean ignoreIPv6ProvisioningLoss = mHasDisabledIpv6OrAcceptRaOnProvLoss
|| (mConfiguration != null && mConfiguration.mUsingMultinetworkPolicyTracker
&& !mCm.shouldAvoidBadWifi());
@@ -1197,18 +1388,31 @@
if (oldLp.hasGlobalIpv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) {
// Although link properties have lost IPv6 default route in this case, if IPv4 is still
// working with appropriate routes and DNS servers, we can keep the current connection
- // without disconnecting from the network, just disable IPv6 on that given network until
- // to the next provisioning. Disabling IPv6 will result in all IPv6 connectivity torn
- // down and all IPv6 sockets being closed, the non-routable IPv6 DNS servers will be
- // stripped out, so applications will be able to reconnect immediately over IPv4. See
- // b/131781810.
+ // without disconnecting from the network, just disable IPv6 or accept_ra parameter on
+ // that given network until to the next provisioning.
+ //
+ // Disabling IPv6 stack will result in all IPv6 connectivity torn down and all IPv6
+ // sockets being closed, the non-routable IPv6 DNS servers will be stripped out, so
+ // applications will be able to reconnect immediately over IPv4. See b/131781810.
+ //
+ // Sometimes disabling IPv6 stack might introduce other issues(see b/179222860),
+ // instead disabling accept_ra will result in only IPv4 provisioning and IPv6 link
+ // local address left on the interface, so applications will be able to reconnect
+ // immediately over IPv4 and keep IPv6 link-local capable.
if (newLp.isIpv4Provisioned()) {
- mInterfaceCtrl.disableIPv6();
- mHasDisabledIPv6OnProvLoss = true;
- delta = PROV_CHANGE_STILL_PROVISIONED;
- if (DBG) {
- mLog.log("Disable IPv6 stack completely when the default router has gone");
+ if (shouldDisableAcceptRaOnProvisioningLoss()) {
+ restartIpv6WithAcceptRaDisabled();
+ } else {
+ mInterfaceCtrl.disableIPv6();
}
+ mNetworkQuirkMetrics.setEvent(NetworkQuirkEvent.QE_IPV6_PROVISIONING_ROUTER_LOST);
+ mNetworkQuirkMetrics.statsWrite();
+ mHasDisabledIpv6OrAcceptRaOnProvLoss = true;
+ delta = PROV_CHANGE_STILL_PROVISIONED;
+ mLog.log(shouldDisableAcceptRaOnProvisioningLoss()
+ ? "Disabled accept_ra parameter "
+ : "Disabled IPv6 stack completely "
+ + "when the IPv6 default router has gone");
} else {
delta = PROV_CHANGE_LOST_PROVISIONING;
}
@@ -1377,6 +1581,92 @@
}
}
+ private void transmitPacket(final ByteBuffer packet, final SocketAddress sockAddress,
+ final String msg) {
+ FileDescriptor sock = null;
+ try {
+ sock = Os.socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, 0 /* protocol */);
+ Os.sendto(sock, packet.array(), 0 /* byteOffset */, packet.limit() /* byteCount */,
+ 0 /* flags */, sockAddress);
+ } catch (SocketException | ErrnoException e) {
+ logError(msg, e);
+ } finally {
+ NetworkStackUtils.closeSocketQuietly(sock);
+ }
+ }
+
+ private void sendGratuitousNA(final Inet6Address srcIp, final Inet6Address targetIp) {
+ final int flags = 0; // R=0, S=0, O=0
+ final Inet6Address dstIp = IPV6_ADDR_ALL_ROUTERS_MULTICAST;
+ // Ethernet multicast destination address: 33:33:00:00:00:02.
+ final MacAddress dstMac = NetworkStackUtils.ipv6MulticastToEthernetMulticast(dstIp);
+ final ByteBuffer packet = NeighborAdvertisement.build(mInterfaceParams.macAddr, dstMac,
+ srcIp, dstIp, flags, targetIp);
+ final SocketAddress sockAddress =
+ SocketUtilsShimImpl.newInstance().makePacketSocketAddress(ETH_P_IPV6,
+ mInterfaceParams.index, dstMac.toByteArray());
+
+ transmitPacket(packet, sockAddress, "Failed to send Gratuitous Neighbor Advertisement");
+ }
+
+ private void sendGratuitousARP(final Inet4Address srcIp) {
+ final ByteBuffer packet = ArpPacket.buildArpPacket(ETHER_BROADCAST /* dstMac */,
+ mInterfaceParams.macAddr.toByteArray() /* srcMac */,
+ srcIp.getAddress() /* targetIp */,
+ ETHER_BROADCAST /* targetHwAddress */,
+ srcIp.getAddress() /* senderIp */, (short) ARP_REPLY);
+ final SocketAddress sockAddress =
+ makePacketSocketAddress(ETH_P_ARP, mInterfaceParams.index);
+
+ transmitPacket(packet, sockAddress, "Failed to send GARP");
+ }
+
+ private static Inet6Address getIpv6LinkLocalAddress(final LinkProperties newLp) {
+ for (LinkAddress la : newLp.getLinkAddresses()) {
+ if (!la.isIpv6()) continue;
+ final Inet6Address ip = (Inet6Address) la.getAddress();
+ if (ip.isLinkLocalAddress()) return ip;
+ }
+ return null;
+ }
+
+ private void maybeSendGratuitousNAs(final LinkProperties lp, boolean afterRoaming) {
+ if (!lp.hasGlobalIpv6Address()) return;
+
+ final Inet6Address srcIp = getIpv6LinkLocalAddress(lp);
+ if (srcIp == null) return;
+
+ // TODO: add experiment with sending only one gratuitous NA packet instead of one
+ // packet per address.
+ for (LinkAddress la : lp.getLinkAddresses()) {
+ if (!la.isIpv6() || !la.isGlobalPreferred()) continue;
+ final Inet6Address targetIp = (Inet6Address) la.getAddress();
+ // Already sent gratuitous NA with this target global IPv6 address. But for
+ // the L2 roaming case, device should always (re)transmit Gratuitous NA for
+ // each IPv6 global unicast address respectively after roaming.
+ if (!afterRoaming && mGratuitousNaTargetAddresses.contains(targetIp)) continue;
+ if (DBG) {
+ mLog.log("send Gratuitous NA from " + srcIp.getHostAddress() + " for "
+ + targetIp.getHostAddress() + (afterRoaming ? " after roaming" : ""));
+ }
+ sendGratuitousNA(srcIp, targetIp);
+ if (!afterRoaming) mGratuitousNaTargetAddresses.add(targetIp);
+ }
+ }
+
+ private void maybeSendGratuitousARP(final LinkProperties lp) {
+ for (LinkAddress address : lp.getLinkAddresses()) {
+ if (address.getAddress() instanceof Inet4Address) {
+ final Inet4Address srcIp = (Inet4Address) address.getAddress();
+ if (DBG) {
+ mLog.log("send GARP for " + srcIp.getHostAddress() + " HW address: "
+ + mInterfaceParams.macAddr);
+ }
+ sendGratuitousARP(srcIp);
+ }
+ }
+ }
+
// Returns false if we have lost provisioning, true otherwise.
private boolean handleLinkPropertiesUpdate(boolean sendCallbacks) {
final LinkProperties newLp = assembleLinkProperties();
@@ -1384,6 +1674,13 @@
return true;
}
+ // Check if new assigned IPv6 GUA is available in the LinkProperties now. If so, initiate
+ // gratuitous multicast unsolicited Neighbor Advertisements as soon as possible to inform
+ // first-hop routers that the new GUA host is goning to use.
+ if (isGratuitousNaEnabled()) {
+ maybeSendGratuitousNAs(newLp, false /* isGratuitousNaAfterRoaming */);
+ }
+
// Either success IPv4 or IPv6 provisioning triggers new LinkProperties update,
// wait for the provisioning completion and record the latency.
mIpProvisioningMetrics.setIPv4ProvisionedLatencyOnFirstTime(newLp.isIpv4Provisioned());
@@ -1554,7 +1851,7 @@
private boolean startIpReachabilityMonitor() {
try {
- mIpReachabilityMonitor = new IpReachabilityMonitor(
+ mIpReachabilityMonitor = mDependencies.getIpReachabilityMonitor(
mContext,
mInterfaceParams,
getHandler(),
@@ -1566,6 +1863,7 @@
}
},
mConfiguration.mUsingMultinetworkPolicyTracker,
+ mDependencies.getIpReachabilityMonitorDeps(mContext, mInterfaceParams.name),
mNetd);
} catch (IllegalArgumentException iae) {
// Failed to start IpReachabilityMonitor. Log it and call
@@ -1639,8 +1937,15 @@
// If the BSSID has not changed, there is nothing to do.
if (info.bssid.equals(mCurrentBssid)) return;
+ // Before trigger probing to the interesting neighbors, send Gratuitous ARP
+ // and Neighbor Advertisment in advance to propgate host's IPv4/v6 addresses.
+ if (isGratuitousArpNaRoamingEnabled()) {
+ maybeSendGratuitousARP(mLinkProperties);
+ maybeSendGratuitousNAs(mLinkProperties, true /* isGratuitousNaAfterRoaming */);
+ }
+
if (mIpReachabilityMonitor != null) {
- mIpReachabilityMonitor.probeAll();
+ mIpReachabilityMonitor.probeAll(true /* dueToRoam */);
}
// Check whether to refresh previous IP lease on L2 roaming happened.
@@ -1661,9 +1966,10 @@
@Override
public void enter() {
stopAllIP();
- mHasDisabledIPv6OnProvLoss = false;
+ setIpv6AcceptRa(2 /* accept_ra */);
+ mHasDisabledIpv6OrAcceptRaOnProvLoss = false;
+ mGratuitousNaTargetAddresses.clear();
- mLinkObserver.clearInterfaceParams();
resetLinkProperties();
if (mStartTimeMillis > 0) {
// Completed a life-cycle; send a final empty LinkProperties
@@ -1735,6 +2041,9 @@
if (mDhcpClient == null) {
// There's no DHCPv4 for which to wait; proceed to stopped.
deferMessage(obtainMessage(CMD_JUMP_STOPPING_TO_STOPPED));
+ } else {
+ mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP);
+ mDhcpClient.doQuit();
}
// Restore the interface MTU to initial value if it has changed.
@@ -1971,6 +2280,14 @@
}
}
+ private boolean isIpv6Enabled() {
+ return mConfiguration.mIPv6ProvisioningMode != PROV_IPV6_DISABLED;
+ }
+
+ private boolean isIpv4Enabled() {
+ return mConfiguration.mIPv4ProvisioningMode != PROV_IPV4_DISABLED;
+ }
+
class RunningState extends State {
private ConnectivityPacketTracker mPacketTracker;
private boolean mDhcpActionInFlight;
@@ -1981,10 +2298,19 @@
apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
apfConfig.multicastFilter = mMulticastFiltering;
// Get the Configuration for ApfFilter from Context
- apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
- apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
+ // Resource settings were moved from ApfCapabilities APIs to NetworkStack resources in S
+ if (ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.R)) {
+ final Resources res = mContext.getResources();
+ apfConfig.ieee802_3Filter = res.getBoolean(R.bool.config_apfDrop802_3Frames);
+ apfConfig.ethTypeBlackList = res.getIntArray(R.array.config_apfEthTypeDenyList);
+ } else {
+ apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
+ apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
+ }
+
apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
- mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
+ mApfFilter = mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
+ mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
@@ -1994,13 +2320,13 @@
mPacketTracker = createPacketTracker();
if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);
- if (mConfiguration.mEnableIPv6 && !startIPv6()) {
+ if (isIpv6Enabled() && !startIPv6()) {
doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6);
return;
}
- if (mConfiguration.mEnableIPv4 && !isUsingPreconnection() && !startIPv4()) {
+ if (isIpv4Enabled() && !isUsingPreconnection() && !startIPv4()) {
doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV4);
return;
@@ -2031,11 +2357,6 @@
mIpReachabilityMonitor = null;
}
- if (mDhcpClient != null) {
- mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP);
- mDhcpClient.doQuit();
- }
-
if (mPacketTracker != null) {
mPacketTracker.stop();
mPacketTracker = null;
@@ -2098,7 +2419,7 @@
// a DHCPv4 RENEW. We used to do this on Wi-Fi framework
// roams.
if (mIpReachabilityMonitor != null) {
- mIpReachabilityMonitor.probeAll();
+ mIpReachabilityMonitor.probeAll(false /* dueToRoam */);
}
break;
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index cc4a851..ff0aafe 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -16,6 +16,7 @@
package android.net.ip;
+import static android.net.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION;
import static android.system.OsConstants.AF_INET6;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
@@ -27,16 +28,17 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.RouteInfo;
-import android.net.netlink.NduseroptMessage;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.StructNdOptPref64;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.Handler;
import android.system.OsConstants;
import android.util.Log;
+import com.android.net.module.util.netlink.NduseroptMessage;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkMessage;
+import com.android.net.module.util.netlink.StructNdOptPref64;
+import com.android.net.module.util.netlink.StructNdOptRdnss;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
import com.android.networkstack.apishim.common.NetworkInformationShim;
import com.android.server.NetworkObserver;
@@ -107,6 +109,7 @@
}
}
+ private final Context mContext;
private final String mInterfaceName;
private final Callback mCallback;
private final LinkProperties mLinkProperties;
@@ -115,13 +118,15 @@
private final AlarmManager mAlarmManager;
private final Configuration mConfig;
private final Handler mHandler;
+ private final IpClient.Dependencies mDependencies;
private final MyNetlinkMonitor mNetlinkMonitor;
private static final boolean DBG = false;
public IpClientLinkObserver(Context context, Handler h, String iface, Callback callback,
- Configuration config, SharedLog log) {
+ Configuration config, SharedLog log, IpClient.Dependencies deps) {
+ mContext = context;
mInterfaceName = iface;
mTag = "NetlinkTracker/" + mInterfaceName;
mCallback = callback;
@@ -134,6 +139,7 @@
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mNetlinkMonitor = new MyNetlinkMonitor(h, log, mTag);
mHandler.post(mNetlinkMonitor::start);
+ mDependencies = deps;
}
public void shutdown() {
@@ -153,6 +159,11 @@
}
}
+ private boolean isNetlinkEventParsingEnabled() {
+ return mDependencies.isFeatureEnabled(mContext, IPCLIENT_PARSE_NETLINK_EVENTS_VERSION,
+ false /* default value */);
+ }
+
@Override
public void onInterfaceRemoved(String iface) {
maybeLog("interfaceRemoved", iface);
@@ -246,17 +257,21 @@
@Override
public void onInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
- if (mInterfaceName.equals(iface)) {
- maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
- final boolean changed = mDnsServerRepository.addServers(lifetime, addresses);
- final boolean linkState;
- if (changed) {
- synchronized (this) {
- mDnsServerRepository.setDnsServersOn(mLinkProperties);
- linkState = getInterfaceLinkStateLocked();
- }
- mCallback.update(linkState);
+ if (isNetlinkEventParsingEnabled()) return;
+ if (!mInterfaceName.equals(iface)) return;
+ maybeLog("interfaceDnsServerInfo", Arrays.toString(addresses));
+ updateInterfaceDnsServerInfo(lifetime, addresses);
+ }
+
+ private void updateInterfaceDnsServerInfo(long lifetime, final String[] addresses) {
+ final boolean changed = mDnsServerRepository.addServers(lifetime, addresses);
+ final boolean linkState;
+ if (changed) {
+ synchronized (this) {
+ mDnsServerRepository.setDnsServersOn(mLinkProperties);
+ linkState = getInterfaceLinkStateLocked();
}
+ mCallback.update(linkState);
}
}
@@ -408,6 +423,15 @@
updatePref64(opt.prefix, now, expiry);
}
+ private void processRdnssOption(StructNdOptRdnss opt) {
+ if (!isNetlinkEventParsingEnabled()) return;
+ final String[] addresses = new String[opt.servers.length];
+ for (int i = 0; i < opt.servers.length; i++) {
+ addresses[i] = opt.servers[i].getHostAddress();
+ }
+ updateInterfaceDnsServerInfo(opt.header.lifetime, addresses);
+ }
+
private void processNduseroptMessage(NduseroptMessage msg, final long whenMs) {
if (msg.family != AF_INET6 || msg.option == null || msg.ifindex != mIfindex) return;
if (msg.icmp_type != (byte) ICMPV6_ROUTER_ADVERTISEMENT) return;
@@ -417,8 +441,12 @@
processPref64Option((StructNdOptPref64) msg.option, whenMs);
break;
+ case StructNdOptRdnss.TYPE:
+ processRdnssOption((StructNdOptRdnss) msg.option);
+ break;
+
default:
- // TODO: implement RDNSS and DNSSL.
+ // TODO: implement DNSSL.
break;
}
}
diff --git a/src/android/net/ip/IpReachabilityMonitor.java b/src/android/net/ip/IpReachabilityMonitor.java
index 3dbe662..0f199e2 100644
--- a/src/android/net/ip/IpReachabilityMonitor.java
+++ b/src/android/net/ip/IpReachabilityMonitor.java
@@ -20,6 +20,8 @@
import static android.net.metrics.IpReachabilityEvent.NUD_FAILED_ORGANIC;
import static android.net.metrics.IpReachabilityEvent.PROVISIONING_LOST;
import static android.net.metrics.IpReachabilityEvent.PROVISIONING_LOST_ORGANIC;
+import static android.net.util.NetworkStackUtils.IP_REACHABILITY_MCAST_RESOLICIT_VERSION;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -30,7 +32,6 @@
import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
-import android.net.netlink.StructNdMsg;
import android.net.util.InterfaceParams;
import android.net.util.SharedLog;
import android.os.ConditionVariable;
@@ -40,12 +41,21 @@
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.stats.connectivity.IpType;
+import android.stats.connectivity.NudEventType;
+import android.stats.connectivity.NudNeighborType;
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.netlink.StructNdMsg;
import com.android.networkstack.R;
+import com.android.networkstack.metrics.IpReachabilityMonitorMetrics;
import java.io.PrintWriter;
import java.net.Inet6Address;
@@ -143,6 +153,10 @@
protected static final int MIN_NUD_SOLICIT_NUM = 5;
protected static final int MAX_NUD_SOLICIT_INTERVAL_MS = 1000;
protected static final int MIN_NUD_SOLICIT_INTERVAL_MS = 750;
+ protected static final int NUD_MCAST_RESOLICIT_NUM = 3;
+ private static final int INVALID_NUD_MCAST_RESOLICIT_NUM = -1;
+
+ private static final int INVALID_LEGACY_NUD_FAILURE_TYPE = -1;
public interface Callback {
/**
@@ -161,6 +175,8 @@
interface Dependencies {
void acquireWakeLock(long durationMs);
IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb);
+ boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled);
+ IpReachabilityMonitorMetrics getIpReachabilityMonitorMetrics();
static Dependencies makeDefault(Context context, String iface) {
final String lockName = TAG + "." + iface;
@@ -176,6 +192,16 @@
NeighborEventConsumer cb) {
return new IpNeighborMonitor(h, log, cb);
}
+
+ public boolean isFeatureEnabled(final Context context, final String name,
+ boolean defaultEnabled) {
+ return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
+ defaultEnabled);
+ }
+
+ public IpReachabilityMonitorMetrics getIpReachabilityMonitorMetrics() {
+ return new IpReachabilityMonitorMetrics();
+ }
};
}
}
@@ -183,25 +209,30 @@
private final InterfaceParams mInterfaceParams;
private final IpNeighborMonitor mIpNeighborMonitor;
private final SharedLog mLog;
- private final Callback mCallback;
private final Dependencies mDependencies;
private final boolean mUsingMultinetworkPolicyTracker;
private final ConnectivityManager mCm;
private final IpConnectivityLog mMetricsLog;
private final Context mContext;
private final INetd mNetd;
+ private final IpReachabilityMonitorMetrics mIpReachabilityMetrics;
private LinkProperties mLinkProperties = new LinkProperties();
private Map<InetAddress, NeighborEvent> mNeighborWatchList = new HashMap<>();
// Time in milliseconds of the last forced probe request.
private volatile long mLastProbeTimeMs;
+ // Time in milliseconds of the last forced probe request due to roam or CMD_CONFIRM.
+ private long mLastProbeDueToRoamMs;
+ private long mLastProbeDueToConfirmMs;
private int mNumSolicits;
private int mInterSolicitIntervalMs;
+ @NonNull
+ private final Callback mCallback;
public IpReachabilityMonitor(
Context context, InterfaceParams ifParams, Handler h, SharedLog log, Callback callback,
- boolean usingMultinetworkPolicyTracker, final INetd netd) {
- this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker,
- Dependencies.makeDefault(context, ifParams.name), new IpConnectivityLog(), netd);
+ boolean usingMultinetworkPolicyTracker, Dependencies dependencies, final INetd netd) {
+ this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker, dependencies,
+ new IpConnectivityLog(), netd);
}
@VisibleForTesting
@@ -225,7 +256,10 @@
// In case the overylaid parameters specify an invalid configuration, set the parameters
// to the hardcoded defaults first, then set them to the values used in the steady state.
try {
- setNeighborParameters(MIN_NUD_SOLICIT_NUM, MIN_NUD_SOLICIT_INTERVAL_MS);
+ int numResolicits = isMulticastResolicitEnabled()
+ ? NUD_MCAST_RESOLICIT_NUM
+ : INVALID_NUD_MCAST_RESOLICIT_NUM;
+ setNeighborParameters(MIN_NUD_SOLICIT_NUM, MIN_NUD_SOLICIT_INTERVAL_MS, numResolicits);
} catch (Exception e) {
Log.e(TAG, "Failed to adjust neighbor parameters with hardcoded defaults");
}
@@ -241,13 +275,16 @@
// TODO: Consider what to do with other states that are not within
// NeighborEvent#isValid() (i.e. NUD_NONE, NUD_INCOMPLETE).
if (event.nudState == StructNdMsg.NUD_FAILED) {
+ // After both unicast probe and multicast probe(if mcast_resolicit is not 0)
+ // attempts fail, trigger the neighbor lost event and disconnect.
mLog.w("ALERT neighbor went from: " + prev + " to: " + event);
handleNeighborLost(event);
} else if (event.nudState == StructNdMsg.NUD_REACHABLE) {
- maybeRestoreNeighborParameters();
+ handleNeighborReachable(prev, event);
}
});
mIpNeighborMonitor.start();
+ mIpReachabilityMetrics = dependencies.getIpReachabilityMonitorMetrics();
}
public void stop() {
@@ -296,6 +333,33 @@
return false;
}
+ private boolean hasDefaultRouterNeighborMacAddressChanged(
+ @Nullable final NeighborEvent prev, @NonNull final NeighborEvent event) {
+ if (prev == null || !isNeighborDefaultRouter(event)) return false;
+ return !event.macAddr.equals(prev.macAddr);
+ }
+
+ private boolean isNeighborDefaultRouter(@NonNull final NeighborEvent event) {
+ // For the IPv6 link-local scoped address, equals() works because the NeighborEvent.ip
+ // doesn't have a scope id and Inet6Address#equals doesn't consider scope id neither.
+ for (RouteInfo route : mLinkProperties.getRoutes()) {
+ if (route.isDefaultRoute() && event.ip.equals(route.getGateway())) return true;
+ }
+ return false;
+ }
+
+ private boolean isNeighborDnsServer(@NonNull final NeighborEvent event) {
+ for (InetAddress dns : mLinkProperties.getDnsServers()) {
+ if (event.ip.equals(dns)) return true;
+ }
+ return false;
+ }
+
+ private boolean isMulticastResolicitEnabled() {
+ return mDependencies.isFeatureEnabled(mContext, IP_REACHABILITY_MCAST_RESOLICIT_VERSION,
+ false /* defaultEnabled */);
+ }
+
public void updateLinkProperties(LinkProperties lp) {
if (!mInterfaceParams.name.equals(lp.getInterfaceName())) {
// TODO: figure out whether / how to cope with interface changes.
@@ -333,6 +397,25 @@
if (DBG) { Log.d(TAG, "clear: " + describeWatchList()); }
}
+ private void handleNeighborReachable(@Nullable final NeighborEvent prev,
+ @NonNull final NeighborEvent event) {
+ if (isMulticastResolicitEnabled()
+ && hasDefaultRouterNeighborMacAddressChanged(prev, event)) {
+ // This implies device has confirmed the neighbor's reachability from
+ // other states(e.g., NUD_PROBE or NUD_STALE), checking if the mac
+ // address hasn't changed is required. If Mac address does change, then
+ // trigger a new neighbor lost event and disconnect.
+ final String logMsg = "ALERT neighbor: " + event.ip
+ + " MAC address changed from: " + prev.macAddr
+ + " to: " + event.macAddr;
+ mLog.w(logMsg);
+ mCallback.notifyLost(event.ip, logMsg);
+ logNudFailed(event, NudEventType.NUD_MAC_ADDRESS_CHANGED);
+ return;
+ }
+ maybeRestoreNeighborParameters();
+ }
+
private void handleNeighborLost(NeighborEvent event) {
final LinkProperties whatIfLp = new LinkProperties(mLinkProperties);
@@ -366,17 +449,17 @@
final boolean lostProvisioning =
(mLinkProperties.isIpv4Provisioned() && !whatIfLp.isIpv4Provisioned())
|| (mLinkProperties.isIpv6Provisioned() && !whatIfLp.isIpv6Provisioned());
+ final NudEventType type = getNudFailureEventType(isFromProbe(),
+ isNudFailureDueToRoam(), lostProvisioning);
if (lostProvisioning) {
final String logMsg = "FAILURE: LOST_PROVISIONING, " + event;
Log.w(TAG, logMsg);
- if (mCallback != null) {
- // TODO: remove |ip| when the callback signature no longer has
- // an InetAddress argument.
- mCallback.notifyLost(ip, logMsg);
- }
+ // TODO: remove |ip| when the callback signature no longer has
+ // an InetAddress argument.
+ mCallback.notifyLost(ip, logMsg);
}
- logNudFailed(lostProvisioning);
+ logNudFailed(event, type);
}
private void maybeRestoreNeighborParameters() {
@@ -400,7 +483,13 @@
return !mUsingMultinetworkPolicyTracker || mCm.shouldAvoidBadWifi();
}
- public void probeAll() {
+ /**
+ * Force probe to verify whether or not the critical on-link neighbours are still reachable.
+ *
+ * @param dueToRoam indicate on which situation forced probe has been sent, e.g., on post
+ * roaming or receiving CMD_CONFIRM from IpClient.
+ */
+ public void probeAll(boolean dueToRoam) {
setNeighbourParametersPostRoaming();
final List<InetAddress> ipProbeList = new ArrayList<>(mNeighborWatchList.keySet());
@@ -421,6 +510,11 @@
logEvent(IpReachabilityEvent.PROBE, rval);
}
mLastProbeTimeMs = SystemClock.elapsedRealtime();
+ if (dueToRoam) {
+ mLastProbeDueToRoamMs = mLastProbeTimeMs;
+ } else {
+ mLastProbeDueToConfirmMs = mLastProbeTimeMs;
+ }
}
private long getProbeWakeLockDuration() {
@@ -450,6 +544,12 @@
private void setNeighborParameters(int numSolicits, int interSolicitIntervalMs)
throws RemoteException, IllegalArgumentException {
+ // Do not set mcast_resolicit param by default.
+ setNeighborParameters(numSolicits, interSolicitIntervalMs, INVALID_NUD_MCAST_RESOLICIT_NUM);
+ }
+
+ private void setNeighborParameters(int numSolicits, int interSolicitIntervalMs,
+ int numResolicits) throws RemoteException, IllegalArgumentException {
Preconditions.checkArgument(numSolicits >= MIN_NUD_SOLICIT_NUM,
"numSolicits must be at least " + MIN_NUD_SOLICIT_NUM);
Preconditions.checkArgument(numSolicits <= MAX_NUD_SOLICIT_NUM,
@@ -464,32 +564,117 @@
Integer.toString(interSolicitIntervalMs));
mNetd.setProcSysNet(family, INetd.NEIGH, mInterfaceParams.name, "ucast_solicit",
Integer.toString(numSolicits));
+ if (numResolicits != INVALID_NUD_MCAST_RESOLICIT_NUM) {
+ mNetd.setProcSysNet(family, INetd.NEIGH, mInterfaceParams.name, "mcast_resolicit",
+ Integer.toString(numResolicits));
+ }
}
mNumSolicits = numSolicits;
mInterSolicitIntervalMs = interSolicitIntervalMs;
}
+ private boolean isFromProbe() {
+ final long duration = SystemClock.elapsedRealtime() - mLastProbeTimeMs;
+ return duration < getProbeWakeLockDuration();
+ }
+
+ private boolean isNudFailureDueToRoam() {
+ if (!isFromProbe()) return false;
+
+ // Check to which probe expiry the curren timestamp gets close when NUD failure event
+ // happens, theoretically that indicates which probe event(due to roam or CMD_CONFIRM)
+ // was triggered eariler.
+ //
+ // Note that this would be incorrect if the probe or confirm was so long ago that the
+ // probe duration has already expired. That cannot happen because isFromProbe would return
+ // false.
+ final long probeExpiryAfterRoam = mLastProbeDueToRoamMs + getProbeWakeLockDuration();
+ final long probeExpiryAfterConfirm =
+ mLastProbeDueToConfirmMs + getProbeWakeLockDuration();
+ final long currentTime = SystemClock.elapsedRealtime();
+ return Math.abs(probeExpiryAfterRoam - currentTime)
+ < Math.abs(probeExpiryAfterConfirm - currentTime);
+ }
+
private void logEvent(int probeType, int errorCode) {
int eventType = probeType | (errorCode & 0xff);
mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
- private void logNudFailed(boolean lostProvisioning) {
- long duration = SystemClock.elapsedRealtime() - mLastProbeTimeMs;
- boolean isFromProbe = (duration < getProbeWakeLockDuration());
- int eventType = nudFailureEventType(isFromProbe, lostProvisioning);
+ private void logNudFailed(final NeighborEvent event, final NudEventType type) {
+ logNeighborLostEvent(event, type);
+
+ // The legacy metrics only record whether the failure came from a probe and whether
+ // the network is still provisioned. They do not record provisioning failures due to
+ // multicast resolicits finding that the MAC address has changed.
+ final int eventType = legacyNudFailureType(type);
+ if (eventType == INVALID_LEGACY_NUD_FAILURE_TYPE) return;
mMetricsLog.log(mInterfaceParams.name, new IpReachabilityEvent(eventType));
}
/**
+ * Returns the neighbor type code corresponding to the given conditions.
+ */
+ private NudNeighborType getNeighborType(final NeighborEvent event) {
+ final boolean isGateway = isNeighborDefaultRouter(event);
+ final boolean isDnsServer = isNeighborDnsServer(event);
+
+ if (isGateway && isDnsServer) return NudNeighborType.NUD_NEIGHBOR_BOTH;
+ if (isGateway && !isDnsServer) return NudNeighborType.NUD_NEIGHBOR_GATEWAY;
+ if (!isGateway && isDnsServer) return NudNeighborType.NUD_NEIGHBOR_DNS;
+ return NudNeighborType.NUD_NEIGHBOR_UNKNOWN;
+ }
+
+ /**
* Returns the NUD failure event type code corresponding to the given conditions.
*/
- private static int nudFailureEventType(boolean isFromProbe, boolean isProvisioningLost) {
- if (isFromProbe) {
- return isProvisioningLost ? PROVISIONING_LOST : NUD_FAILED;
- } else {
- return isProvisioningLost ? PROVISIONING_LOST_ORGANIC : NUD_FAILED_ORGANIC;
+ private static NudEventType getNudFailureEventType(boolean isFromProbe, boolean isDueToRoam,
+ boolean isProvisioningLost) {
+ if (!isFromProbe) {
+ return isProvisioningLost
+ ? NudEventType.NUD_ORGANIC_FAILED_CRITICAL
+ : NudEventType.NUD_ORGANIC_FAILED;
+ }
+ return isProvisioningLost
+ ? isDueToRoam
+ ? NudEventType.NUD_POST_ROAMING_FAILED_CRITICAL
+ : NudEventType.NUD_CONFIRM_FAILED_CRITICAL
+ : isDueToRoam
+ ? NudEventType.NUD_POST_ROAMING_FAILED
+ : NudEventType.NUD_CONFIRM_FAILED;
+ }
+
+ /**
+ * Log NUD failure metrics with new Westworld APIs while the function using mMetricsLog API
+ * still sends the legacy metrics, @see #logNudFailed.
+ */
+ private void logNeighborLostEvent(final NeighborEvent event, final NudEventType type) {
+ final IpType ipType = (event.ip instanceof Inet6Address) ? IpType.IPV6 : IpType.IPV4;
+ mIpReachabilityMetrics.setNudIpType(ipType);
+ mIpReachabilityMetrics.setNudNeighborType(getNeighborType(event));
+ mIpReachabilityMetrics.setNudEventType(type);
+ mIpReachabilityMetrics.statsWrite();
+ }
+
+ /**
+ * Returns the NUD failure event type code corresponding to the given conditions.
+ */
+ private static int legacyNudFailureType(final NudEventType type) {
+ switch (type) {
+ case NUD_POST_ROAMING_FAILED:
+ case NUD_CONFIRM_FAILED:
+ return NUD_FAILED;
+ case NUD_POST_ROAMING_FAILED_CRITICAL:
+ case NUD_CONFIRM_FAILED_CRITICAL:
+ return PROVISIONING_LOST;
+ case NUD_ORGANIC_FAILED:
+ return NUD_FAILED_ORGANIC;
+ case NUD_ORGANIC_FAILED_CRITICAL:
+ return PROVISIONING_LOST_ORGANIC;
+ default:
+ // Do not log legacy event
+ return INVALID_LEGACY_NUD_FAILURE_TYPE;
}
}
}
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java
index 5c11733..6dc2a5b 100755
--- a/src/android/net/util/NetworkStackUtils.java
+++ b/src/android/net/util/NetworkStackUtils.java
@@ -17,12 +17,16 @@
package android.net.util;
import android.content.Context;
+import android.net.MacAddress;
+
+import androidx.annotation.NonNull;
import com.android.net.module.util.DeviceConfigUtils;
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.SocketException;
/**
@@ -232,6 +236,39 @@
*/
public static final String VALIDATION_METRICS_VERSION = "validation_metrics_version";
+ /**
+ * Experiment flag to enable sending gratuitous multicast unsolicited Neighbor Advertisements
+ * to propagate new assigned IPv6 GUA as quickly as possible.
+ */
+ public static final String IPCLIENT_GRATUITOUS_NA_VERSION = "ipclient_gratuitous_na_version";
+
+ /**
+ * Experiment flag to enable sending Gratuitous APR and Gratuitous Neighbor Advertisement for
+ * all assigned IPv4 and IPv6 GUAs after completing L2 roaming.
+ */
+ public static final String IPCLIENT_GARP_NA_ROAMING_VERSION =
+ "ipclient_garp_na_roaming_version";
+
+ /**
+ * Experiment flag to enable parsing netlink events from kernel directly instead from netd aidl
+ * interface.
+ */
+ public static final String IPCLIENT_PARSE_NETLINK_EVENTS_VERSION =
+ "ipclient_parse_netlink_events_version";
+
+ /**
+ * Experiment flag to disable accept_ra parameter when IPv6 provisioning loss happens due to
+ * the default route has gone.
+ */
+ public static final String IPCLIENT_DISABLE_ACCEPT_RA_VERSION = "ipclient_disable_accept_ra";
+
+ /**
+ * Experiment flag to enable "mcast_resolicit" neighbor parameter in IpReachabilityMonitor,
+ * set it to 3 by default.
+ */
+ public static final String IP_REACHABILITY_MCAST_RESOLICIT_VERSION =
+ "ip_reachability_mcast_resolicit_version";
+
static {
System.loadLibrary("networkstackutilsjni");
}
@@ -247,6 +284,21 @@
}
/**
+ * Convert IPv6 multicast address to ethernet multicast address in network order.
+ */
+ public static MacAddress ipv6MulticastToEthernetMulticast(@NonNull final Inet6Address addr) {
+ final byte[] etherMulticast = new byte[6];
+ final byte[] ipv6Multicast = addr.getAddress();
+ etherMulticast[0] = (byte) 0x33;
+ etherMulticast[1] = (byte) 0x33;
+ etherMulticast[2] = ipv6Multicast[12];
+ etherMulticast[3] = ipv6Multicast[13];
+ etherMulticast[4] = ipv6Multicast[14];
+ etherMulticast[5] = ipv6Multicast[15];
+ return MacAddress.fromBytes(etherMulticast);
+ }
+
+ /**
* Attaches a socket filter that accepts DHCP packets to the given socket.
*/
public static native void attachDhcpFilter(FileDescriptor fd) throws SocketException;
diff --git a/src/com/android/networkstack/NetworkStackNotifier.java b/src/com/android/networkstack/NetworkStackNotifier.java
index 0558d3a..acf3c95 100644
--- a/src/com/android/networkstack/NetworkStackNotifier.java
+++ b/src/com/android/networkstack/NetworkStackNotifier.java
@@ -237,8 +237,8 @@
// If the venue friendly name is available (in Passpoint use-case), display it.
// Otherwise, display the SSID.
- final String friendlyName = capportData.getVenueFriendlyName();
- final String venueDisplayName = TextUtils.isEmpty(friendlyName)
+ final CharSequence friendlyName = capportData.getVenueFriendlyName();
+ final CharSequence venueDisplayName = TextUtils.isEmpty(friendlyName)
? getSsid(networkStatus) : friendlyName;
builder = getNotificationBuilder(channel, networkStatus, res, venueDisplayName)
@@ -284,9 +284,9 @@
private Notification.Builder getNotificationBuilder(@NonNull String channelId,
@NonNull TrackedNetworkStatus networkStatus, @NonNull Resources res,
- @NonNull String ssid) {
+ @NonNull CharSequence networkIdentifier) {
return new Notification.Builder(mContext, channelId)
- .setContentTitle(ssid)
+ .setContentTitle(networkIdentifier)
.setSmallIcon(R.drawable.icon_wifi);
}
diff --git a/src/com/android/networkstack/metrics/IpProvisioningMetrics.java b/src/com/android/networkstack/metrics/IpProvisioningMetrics.java
index b015a51..5ca996e 100644
--- a/src/com/android/networkstack/metrics/IpProvisioningMetrics.java
+++ b/src/com/android/networkstack/metrics/IpProvisioningMetrics.java
@@ -157,17 +157,17 @@
mStatsBuilder.setDhcpSession(mDhcpSessionBuilder);
mStatsBuilder.setProvisioningDurationMicros(mWatch.stop());
mStatsBuilder.setRandomNumber((int) (Math.random() * 1000));
- final NetworkIpProvisioningReported Stats = mStatsBuilder.build();
- final byte[] DhcpSession = Stats.getDhcpSession().toByteArray();
+ final NetworkIpProvisioningReported stats = mStatsBuilder.build();
+ final byte[] DhcpSession = stats.getDhcpSession().toByteArray();
NetworkStackStatsLog.write(NetworkStackStatsLog.NETWORK_IP_PROVISIONING_REPORTED,
- Stats.getTransportType().getNumber(),
- Stats.getIpv4LatencyMicros(),
- Stats.getIpv6LatencyMicros(),
- Stats.getProvisioningDurationMicros(),
- Stats.getDisconnectCode().getNumber(),
+ stats.getTransportType().getNumber(),
+ stats.getIpv4LatencyMicros(),
+ stats.getIpv6LatencyMicros(),
+ stats.getProvisioningDurationMicros(),
+ stats.getDisconnectCode().getNumber(),
DhcpSession,
- Stats.getRandomNumber());
+ stats.getRandomNumber());
mWatch.reset();
- return Stats;
+ return stats;
}
}
diff --git a/src/com/android/networkstack/metrics/IpReachabilityMonitorMetrics.java b/src/com/android/networkstack/metrics/IpReachabilityMonitorMetrics.java
new file mode 100644
index 0000000..401de4a
--- /dev/null
+++ b/src/com/android/networkstack/metrics/IpReachabilityMonitorMetrics.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.metrics;
+
+import android.stats.connectivity.IpType;
+import android.stats.connectivity.NudEventType;
+import android.stats.connectivity.NudNeighborType;
+
+/**
+ * Class to record the network stack IpReachabilityMonitor metrics into statsd.
+ *
+ * This class is not thread-safe, and should always be accessed from the same thread.
+ *
+ * @hide
+ */
+public class IpReachabilityMonitorMetrics {
+ private final NetworkIpReachabilityMonitorReported.Builder mStatsBuilder =
+ NetworkIpReachabilityMonitorReported.newBuilder();
+
+ /**
+ * Write the NUD event type into mStatsBuilder.
+ */
+ public void setNudEventType(final NudEventType type) {
+ mStatsBuilder.setEventType(type);
+ }
+
+ /**
+ * Write the NUD probe type(IPv4 or IPv6) into mStatsBuilder.
+ */
+ public void setNudIpType(final IpType type) {
+ mStatsBuilder.setIpType(type);
+ }
+
+ /**
+ * Write the NUD probe neighbor type into mStatsBuilder.
+ */
+ public void setNudNeighborType(final NudNeighborType type) {
+ mStatsBuilder.setNeighborType(type);
+ }
+
+ /**
+ * Write the NetworkIpReachabilityMonitorReported proto into statsd.
+ */
+ public NetworkIpReachabilityMonitorReported statsWrite() {
+ final NetworkIpReachabilityMonitorReported stats = mStatsBuilder.build();
+ NetworkStackStatsLog.write(NetworkStackStatsLog.NETWORK_IP_REACHABILITY_MONITOR_REPORTED,
+ stats.getEventType().getNumber(),
+ stats.getIpType().getNumber(),
+ stats.getNeighborType().getNumber());
+ return stats;
+ }
+}
diff --git a/src/com/android/networkstack/metrics/NetworkQuirkMetrics.java b/src/com/android/networkstack/metrics/NetworkQuirkMetrics.java
new file mode 100644
index 0000000..dee4504
--- /dev/null
+++ b/src/com/android/networkstack/metrics/NetworkQuirkMetrics.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.metrics;
+
+import android.stats.connectivity.NetworkQuirkEvent;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Class to record the network Quirk event into statsd.
+ * @hide
+ */
+public class NetworkQuirkMetrics {
+ private final Dependencies mDependencies;
+ private final NetworkStackQuirkReported.Builder mStatsBuilder =
+ NetworkStackQuirkReported.newBuilder();
+ /**
+ * Dependencies of {@link NetworkQuirkMetrics}, useful for testing.
+ */
+ @VisibleForTesting
+ public static class Dependencies {
+ /**
+ * @see NetworkStackStatsLog#write.
+ */
+ public void writeStats(int event) {
+ NetworkStackStatsLog.write(NetworkStackStatsLog.NETWORK_STACK_QUIRK_REPORTED,
+ 0, event);
+ }
+ }
+
+ /**
+ * Get a NetworkQuirkMetrics instance.
+ */
+ public NetworkQuirkMetrics() {
+ this(new Dependencies());
+ }
+
+ @VisibleForTesting
+ public NetworkQuirkMetrics(Dependencies deps) {
+ mDependencies = deps;
+ }
+
+ /**
+ * Write the network Quirk Event into mStatsBuilder.
+ */
+ public void setEvent(NetworkQuirkEvent event) {
+ mStatsBuilder.setEvent(event);
+ }
+
+ /**
+ * Write the NetworkStackQuirkReported proto into statsd.
+ */
+ public NetworkStackQuirkReported statsWrite() {
+ final NetworkStackQuirkReported stats = mStatsBuilder.build();
+ mDependencies.writeStats(stats.getEvent().getNumber());
+ return stats;
+ }
+}
diff --git a/src/com/android/networkstack/metrics/stats.proto b/src/com/android/networkstack/metrics/stats.proto
index 2b0a704..c09f082 100644
--- a/src/com/android/networkstack/metrics/stats.proto
+++ b/src/com/android/networkstack/metrics/stats.proto
@@ -172,3 +172,19 @@
// Record each Quirk event
optional .android.stats.connectivity.NetworkQuirkEvent event = 2;
}
+
+/**
+ * Logs Neighbor Unreachability Detection probe event.
+ * Logged from:
+ * src/com/android/networkstack/metrics/IpReachabilityMonitorMetrics.java
+ */
+message NetworkIpReachabilityMonitorReported {
+ // Neighbor Unreachability Detection event.
+ optional .android.stats.connectivity.NudEventType event_type = 1;
+
+ // NUD probe based on IPv4 ARP or IPv6 ND packet.
+ optional .android.stats.connectivity.IpType ip_type = 2;
+
+ // NUD neighbor type, default gateway, DNS server or both.
+ optional .android.stats.connectivity.NudNeighborType neighbor_type = 3;
+}
diff --git a/src/com/android/networkstack/netlink/TcpSocketTracker.java b/src/com/android/networkstack/netlink/TcpSocketTracker.java
index 770e85a..b5eafd6 100644
--- a/src/com/android/networkstack/netlink/TcpSocketTracker.java
+++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java
@@ -15,13 +15,6 @@
*/
package com.android.networkstack.netlink;
-import static android.net.netlink.InetDiagMessage.InetDiagReqV2;
-import static android.net.netlink.NetlinkConstants.INET_DIAG_MEMINFO;
-import static android.net.netlink.NetlinkConstants.NLMSG_DONE;
-import static android.net.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
-import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
import static android.net.util.DataStallUtils.CONFIG_MIN_PACKETS_THRESHOLD;
import static android.net.util.DataStallUtils.CONFIG_TCP_PACKETS_FAIL_PERCENTAGE;
import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_MIN_PACKETS_THRESHOLD;
@@ -38,14 +31,18 @@
import static android.system.OsConstants.SOL_SOCKET;
import static android.system.OsConstants.SO_SNDTIMEO;
+import static com.android.net.module.util.netlink.InetDiagMessage.inetDiagReqV2;
+import static com.android.net.module.util.netlink.NetlinkConstants.INET_DIAG_MEMINFO;
+import static com.android.net.module.util.netlink.NetlinkConstants.NLMSG_DONE;
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+
import android.content.Context;
import android.net.INetd;
import android.net.MarkMaskParcel;
import android.net.Network;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.StructInetDiagMsg;
-import android.net.netlink.StructNlMsgHdr;
import android.net.util.NetworkStackUtils;
import android.net.util.SocketUtils;
import android.os.AsyncTask;
@@ -66,6 +63,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkSocket;
+import com.android.net.module.util.netlink.StructInetDiagMsg;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
import com.android.networkstack.apishim.NetworkShimImpl;
import com.android.networkstack.apishim.common.ShimUtils;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
@@ -114,7 +115,7 @@
* Request to send to kernel to request tcp info.
*
* Key: Ip family type.
- * Value: Bytes array represent the {@Code InetDiagReqV2}.
+ * Value: Bytes array represent the {@Code inetDiagReqV2}.
*/
private final SparseArray<byte[]> mSockDiagMsg = new SparseArray<>();
private final Dependencies mDependencies;
@@ -160,7 +161,7 @@
for (final int family : ADDRESS_FAMILIES) {
mSockDiagMsg.put(
family,
- InetDiagReqV2(IPPROTO_TCP,
+ inetDiagReqV2(IPPROTO_TCP,
null /* local addr */,
null /* remote addr */,
family,
diff --git a/src/com/android/networkstack/packets/NeighborAdvertisement.java b/src/com/android/networkstack/packets/NeighborAdvertisement.java
new file mode 100644
index 0000000..ef38314
--- /dev/null
+++ b/src/com/android/networkstack/packets/NeighborAdvertisement.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.packets;
+
+import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NA_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
+
+import android.net.MacAddress;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.net.module.util.Ipv6Utils;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.structs.EthernetHeader;
+import com.android.net.module.util.structs.Icmpv6Header;
+import com.android.net.module.util.structs.Ipv6Header;
+import com.android.net.module.util.structs.LlaOption;
+import com.android.net.module.util.structs.NaHeader;
+
+import java.net.Inet6Address;
+import java.nio.ByteBuffer;
+
+/**
+ * Defines basic data and operations needed to build and parse Neighbor Advertisement packet.
+ *
+ * @hide
+ */
+public class NeighborAdvertisement {
+ @NonNull
+ public final EthernetHeader ethHdr;
+ @NonNull
+ public final Ipv6Header ipv6Hdr;
+ @NonNull
+ public final Icmpv6Header icmpv6Hdr;
+ @NonNull
+ public final NaHeader naHdr;
+ @Nullable
+ public final LlaOption tlla;
+
+ public NeighborAdvertisement(@NonNull final EthernetHeader ethHdr,
+ @NonNull final Ipv6Header ipv6Hdr, @NonNull final Icmpv6Header icmpv6Hdr,
+ @NonNull final NaHeader naHdr, @Nullable final LlaOption tlla) {
+ this.ethHdr = ethHdr;
+ this.ipv6Hdr = ipv6Hdr;
+ this.icmpv6Hdr = icmpv6Hdr;
+ this.naHdr = naHdr;
+ this.tlla = tlla;
+ }
+
+ /**
+ * Convert a Neighbor Advertisement instance to ByteBuffer.
+ */
+ public ByteBuffer toByteBuffer() {
+ final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+ final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
+ final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
+ final int naHeaderLen = Struct.getSize(NaHeader.class);
+ final int tllaOptionLen = (tlla == null) ? 0 : Struct.getSize(LlaOption.class);
+ final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
+ + icmpv6HeaderLen + naHeaderLen + tllaOptionLen);
+
+ ethHdr.writeToByteBuffer(packet);
+ ipv6Hdr.writeToByteBuffer(packet);
+ icmpv6Hdr.writeToByteBuffer(packet);
+ naHdr.writeToByteBuffer(packet);
+ if (tlla != null) {
+ tlla.writeToByteBuffer(packet);
+ }
+ packet.flip();
+
+ return packet;
+ }
+
+ /**
+ * Build a Neighbor Advertisement packet from the required specified parameters.
+ */
+ public static ByteBuffer build(@NonNull final MacAddress srcMac,
+ @NonNull final MacAddress dstMac, @NonNull final Inet6Address srcIp,
+ @NonNull final Inet6Address dstIp, int flags, @NonNull final Inet6Address target) {
+ final ByteBuffer tlla = LlaOption.build((byte) ICMPV6_ND_OPTION_TLLA, srcMac);
+ return Ipv6Utils.buildNaPacket(srcMac, dstMac, srcIp, dstIp, flags, target, tlla);
+ }
+
+ /**
+ * Parse a Neighbor Advertisement packet from ByteBuffer.
+ */
+ public static NeighborAdvertisement parse(@NonNull final byte[] recvbuf, final int length)
+ throws ParseException {
+ if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NA_HEADER_LEN
+ || recvbuf.length < length) {
+ throw new ParseException("Invalid packet length: " + length);
+ }
+ final ByteBuffer packet = ByteBuffer.wrap(recvbuf, 0, length);
+
+ // Parse each header and option in Neighbor Advertisement packet in order.
+ final EthernetHeader ethHdr = Struct.parse(EthernetHeader.class, packet);
+ final Ipv6Header ipv6Hdr = Struct.parse(Ipv6Header.class, packet);
+ final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, packet);
+ final NaHeader naHdr = Struct.parse(NaHeader.class, packet);
+ final LlaOption tlla = (packet.remaining() == 0)
+ ? null
+ : Struct.parse(LlaOption.class, packet);
+
+ return new NeighborAdvertisement(ethHdr, ipv6Hdr, icmpv6Hdr, naHdr, tlla);
+ }
+
+ /**
+ * Thrown when parsing Neighbor Advertisement packet failed.
+ */
+ public static class ParseException extends Exception {
+ ParseException(String message) {
+ super(message);
+ }
+ }
+}
diff --git a/src/com/android/networkstack/packets/NeighborSolicitation.java b/src/com/android/networkstack/packets/NeighborSolicitation.java
new file mode 100644
index 0000000..5c3e40a
--- /dev/null
+++ b/src/com/android/networkstack/packets/NeighborSolicitation.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.packets;
+
+import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NS_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
+
+import android.net.MacAddress;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.net.module.util.Ipv6Utils;
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.structs.EthernetHeader;
+import com.android.net.module.util.structs.Icmpv6Header;
+import com.android.net.module.util.structs.Ipv6Header;
+import com.android.net.module.util.structs.LlaOption;
+import com.android.net.module.util.structs.NsHeader;
+
+import java.net.Inet6Address;
+import java.nio.ByteBuffer;
+
+/**
+ * Defines basic data and operations needed to build and parse Neighbor Solicitation packet.
+ *
+ * @hide
+ */
+public class NeighborSolicitation {
+ @NonNull
+ public final EthernetHeader ethHdr;
+ @NonNull
+ public final Ipv6Header ipv6Hdr;
+ @NonNull
+ public final Icmpv6Header icmpv6Hdr;
+ @NonNull
+ public final NsHeader nsHdr;
+ @Nullable
+ public final LlaOption slla;
+
+ public NeighborSolicitation(@NonNull final EthernetHeader ethHdr,
+ @NonNull final Ipv6Header ipv6Hdr, @NonNull final Icmpv6Header icmpv6Hdr,
+ @NonNull final NsHeader nsHdr, @Nullable final LlaOption slla) {
+ this.ethHdr = ethHdr;
+ this.ipv6Hdr = ipv6Hdr;
+ this.icmpv6Hdr = icmpv6Hdr;
+ this.nsHdr = nsHdr;
+ this.slla = slla;
+ }
+
+ /**
+ * Convert a Neighbor Solicitation instance to ByteBuffer.
+ */
+ public ByteBuffer toByteBuffer() {
+ final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+ final int ipv6HeaderLen = Struct.getSize(Ipv6Header.class);
+ final int icmpv6HeaderLen = Struct.getSize(Icmpv6Header.class);
+ final int nsHeaderLen = Struct.getSize(NsHeader.class);
+ final int sllaOptionLen = (slla == null) ? 0 : Struct.getSize(LlaOption.class);
+ final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
+ + icmpv6HeaderLen + nsHeaderLen + sllaOptionLen);
+
+ ethHdr.writeToByteBuffer(packet);
+ ipv6Hdr.writeToByteBuffer(packet);
+ icmpv6Hdr.writeToByteBuffer(packet);
+ nsHdr.writeToByteBuffer(packet);
+ if (slla != null) {
+ slla.writeToByteBuffer(packet);
+ }
+ packet.flip();
+
+ return packet;
+ }
+
+ /**
+ * Build a Neighbor Solicitation packet from the required specified parameters.
+ */
+ public static ByteBuffer build(@NonNull final MacAddress srcMac,
+ @NonNull final MacAddress dstMac, @NonNull final Inet6Address srcIp,
+ @NonNull final Inet6Address dstIp, @NonNull final Inet6Address target) {
+ final ByteBuffer slla = LlaOption.build((byte) ICMPV6_ND_OPTION_SLLA, srcMac);
+ return Ipv6Utils.buildNsPacket(srcMac, dstMac, srcIp, dstIp, target, slla);
+ }
+
+ /**
+ * Parse a Neighbor Solicitation packet from ByteBuffer.
+ */
+ public static NeighborSolicitation parse(@NonNull final byte[] recvbuf, final int length)
+ throws ParseException {
+ if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_NS_HEADER_LEN
+ || recvbuf.length < length) {
+ throw new ParseException("Invalid packet length: " + length);
+ }
+ final ByteBuffer packet = ByteBuffer.wrap(recvbuf, 0, length);
+
+ // Parse each header and option in Neighbor Solicitation packet in order.
+ final EthernetHeader ethHdr = Struct.parse(EthernetHeader.class, packet);
+ final Ipv6Header ipv6Hdr = Struct.parse(Ipv6Header.class, packet);
+ final Icmpv6Header icmpv6Hdr = Struct.parse(Icmpv6Header.class, packet);
+ final NsHeader nsHdr = Struct.parse(NsHeader.class, packet);
+ final LlaOption slla = (packet.remaining() == 0)
+ ? null
+ : Struct.parse(LlaOption.class, packet);
+
+ return new NeighborSolicitation(ethHdr, ipv6Hdr, icmpv6Hdr, nsHdr, slla);
+ }
+
+ /**
+ * Thrown when parsing Neighbor Solicitation packet failed.
+ */
+ public static class ParseException extends Exception {
+ ParseException(String message) {
+ super(message);
+ }
+ }
+}
diff --git a/src/com/android/networkstack/util/DnsUtils.java b/src/com/android/networkstack/util/DnsUtils.java
index 83f2daf..622f56a 100644
--- a/src/com/android/networkstack/util/DnsUtils.java
+++ b/src/com/android/networkstack/util/DnsUtils.java
@@ -29,7 +29,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.internal.util.TrafficStatsConstants;
+import com.android.net.module.util.NetworkStackConstants;
import com.android.server.connectivity.NetworkMonitor.DnsLogFunc;
import java.net.InetAddress;
@@ -126,7 +126,7 @@
// look at the tag at all. Given that this is a library, the tag should be passed in by the
// caller.
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_PROBE);
+ NetworkStackConstants.TAG_SYSTEM_PROBE);
if (type == TYPE_ADDRCONFIG) {
dnsResolver.query(network, host, flag, r -> r.run(), null /* cancellationSignal */,
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index f8a9bab..948ce8d 100755
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -16,13 +16,12 @@
package com.android.server.connectivity;
+import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
import static android.net.CaptivePortal.APP_RETURN_UNWANTED;
import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.DnsResolver.FLAG_EMPTY;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
@@ -33,10 +32,10 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_SKIPPED;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.captiveportal.CaptivePortalProbeSpec.parseCaptivePortalProbeSpecs;
import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
@@ -127,12 +126,11 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.UserHandle;
+import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.stats.connectivity.ProbeResult;
import android.stats.connectivity.ProbeType;
-import android.telephony.AccessNetworkConstants;
import android.telephony.CellIdentityNr;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
@@ -141,8 +139,6 @@
import android.telephony.CellInfoTdscdma;
import android.telephony.CellInfoWcdma;
import android.telephony.CellSignalStrength;
-import android.telephony.NetworkRegistrationInfo;
-import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -161,13 +157,15 @@
import com.android.internal.util.RingBufferIndices;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
-import com.android.internal.util.TrafficStatsConstants;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.NetworkStackConstants;
import com.android.networkstack.NetworkStackNotifier;
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
+import com.android.networkstack.apishim.api29.ConstantsShim;
import com.android.networkstack.apishim.common.CaptivePortalDataShim;
+import com.android.networkstack.apishim.common.NetworkInformationShim;
import com.android.networkstack.apishim.common.ShimUtils;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.metrics.DataStallDetectionStats;
@@ -224,6 +222,9 @@
private static final String TAG = NetworkMonitor.class.getSimpleName();
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ // TODO(b/185082309): For flaky test debug only, remove it after fixing.
+ private static final boolean DDBG_STALL = "cf_x86_auto-userdebug".equals(
+ SystemProperties.get("ro.build.flavor", ""));
private static final boolean VDBG_STALL = Log.isLoggable(TAG, Log.DEBUG);
private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) "
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
@@ -388,10 +389,15 @@
private static final int CMD_BANDWIDTH_CHECK_COMPLETE = 23;
/**
- * Message to self to know the bandwidth check is timeouted.
+ * Message to self to know the bandwidth check has timed out.
*/
private static final int CMD_BANDWIDTH_CHECK_TIMEOUT = 24;
+ /**
+ * Message to self to notify resource configuration is changed.
+ */
+ private static final int EVENT_RESOURCE_CONFIG_CHANGED = 25;
+
// Start mReevaluateDelayMs at this value and double.
@VisibleForTesting
static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
@@ -416,7 +422,6 @@
private String mPrivateDnsProviderHostname = "";
private final Context mContext;
- private final Context mCustomizedContext;
private final INetworkMonitorCallbacks mCallback;
private final int mCallbackVersion;
private final Network mCleartextDnsNetwork;
@@ -431,13 +436,21 @@
private final TcpSocketTracker mTcpTracker;
// Configuration values for captive portal detection probes.
private final String mCaptivePortalUserAgent;
- private final URL[] mCaptivePortalFallbackUrls;
- @NonNull
- private final URL[] mCaptivePortalHttpUrls;
- @NonNull
- private final URL[] mCaptivePortalHttpsUrls;
+ // Configuration values in setting providers for captive portal detection probes
+ private final String mCaptivePortalHttpsUrlFromSetting;
+ private final String mCaptivePortalHttpUrlFromSetting;
@Nullable
private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs;
+
+ // The probing URLs may be updated after constructor if system notifies configuration changed.
+ // Thus, these probing URLs should only be accessed in the StateMachine thread.
+ @NonNull
+ private URL[] mCaptivePortalFallbackUrls;
+ @NonNull
+ private URL[] mCaptivePortalHttpUrls;
+ @NonNull
+ private URL[] mCaptivePortalHttpsUrls;
+
// Configuration values for network bandwidth check.
@Nullable
private final String mEvaluatingBandwidthUrl;
@@ -511,10 +524,13 @@
private @EvaluationType int mDataStallTypeToCollect;
private boolean mAcceptPartialConnectivity = false;
private final EvaluationState mEvaluationState = new EvaluationState();
-
+ @NonNull
+ private final BroadcastReceiver mConfigurationReceiver;
private final boolean mPrivateIpNoInternetEnabled;
private final boolean mMetricsEnabled;
+ @NonNull
+ private final NetworkInformationShim mInfoShim = NetworkInformationShimImpl.newInstance();
// The validation metrics are accessed by individual probe threads, and by the StateMachine
// thread. All accesses must be synchronized to make sure the StateMachine thread can see
@@ -573,7 +589,6 @@
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mNotifier = serviceManager.getNotifier();
- mCustomizedContext = getCustomizedContextOrDefault();
// CHECKSTYLE:OFF IndentationCheck
addState(mDefaultState);
@@ -588,16 +603,18 @@
setInitialState(mDefaultState);
// CHECKSTYLE:ON IndentationCheck
+ mCaptivePortalHttpsUrlFromSetting =
+ mDependencies.getSetting(context, CAPTIVE_PORTAL_HTTPS_URL, null);
+ mCaptivePortalHttpUrlFromSetting =
+ mDependencies.getSetting(context, CAPTIVE_PORTAL_HTTP_URL, null);
mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
mPrivateIpNoInternetEnabled = getIsPrivateIpNoInternetEnabled();
mMetricsEnabled = deps.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
NetworkStackUtils.VALIDATION_METRICS_VERSION, true /* defaultEnabled */);
mUseHttps = getUseHttpsValidation();
mCaptivePortalUserAgent = getCaptivePortalUserAgent();
- mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls();
- mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls();
- mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
- mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
+ mCaptivePortalFallbackSpecs =
+ makeCaptivePortalFallbackProbeSpecs(getCustomizedContextOrDefault());
mRandom = deps.getRandom();
// TODO: Evaluate to move data stall configuration to a specific class.
mConsecutiveDnsTimeoutThreshold = getConsecutiveDnsTimeoutThreshold();
@@ -616,7 +633,14 @@
mEvaluatingBandwidthTimeoutMs = getResIntConfig(mContext,
R.integer.config_evaluating_bandwidth_timeout_ms,
DEFAULT_EVALUATING_BANDWIDTH_TIMEOUT_MS);
-
+ mConfigurationReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
+ sendMessage(EVENT_RESOURCE_CONFIG_CHANGED);
+ }
+ }
+ };
// Provide empty LinkProperties and NetworkCapabilities to make sure they are never null,
// even before notifyNetworkConnected.
mLinkProperties = new LinkProperties();
@@ -634,6 +658,13 @@
/**
* Request the NetworkMonitor to reevaluate the network.
+ *
+ * TODO : refactor reevaluation to introduce rate limiting. If the system finds a network is
+ * validated but some app can't access their server, or the network is behind a captive portal
+ * that only lets the validation URL through, apps may be calling reportNetworkConnectivity
+ * often, causing many revalidation attempts. Meanwhile, reevaluation attempts that result
+ * from actions that may affect the validation status (e.g. the user just logged in through
+ * the captive portal app) should never be skipped because of the rate limitation.
*/
public void forceReevaluation(int responsibleUid) {
sendMessage(CMD_FORCE_REEVALUATION, responsibleUid, 0);
@@ -671,6 +702,7 @@
(Pair<LinkProperties, NetworkCapabilities>) connectedMsg.obj;
mLinkProperties = attrs.first;
mNetworkCapabilities = attrs.second;
+ suppressNotificationIfNetworkRestricted();
}
/**
@@ -735,6 +767,12 @@
return NetworkMonitorUtils.isPrivateDnsValidationRequired(mNetworkCapabilities);
}
+ private void suppressNotificationIfNetworkRestricted() {
+ if (!mNetworkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+ mDontDisplaySigninNotification = true;
+ }
+ }
+
private void notifyNetworkTested(NetworkTestResultParcelable result) {
try {
if (mCallbackVersion <= 5) {
@@ -853,6 +891,18 @@
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@Override
+ public void enter() {
+ // Register configuration broadcast here instead of constructor to prevent start() was
+ // not called yet when the broadcast is received and cause crash.
+ mContext.registerReceiver(mConfigurationReceiver,
+ new IntentFilter(ACTION_CONFIGURATION_CHANGED));
+ checkAndRenewResourceConfig();
+ Log.d(TAG, "Starting on network " + mNetwork
+ + " with capport HTTPS URL " + Arrays.toString(mCaptivePortalHttpsUrls)
+ + " and HTTP URL " + Arrays.toString(mCaptivePortalHttpUrls));
+ }
+
+ @Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_NETWORK_CONNECTED:
@@ -907,6 +957,18 @@
// If the user wants to use this network anyway, there is no need to
// perform the bandwidth check even if configured.
mIsBandwidthCheckPassedOrIgnored = true;
+ // If the user wants to use this network anyway, it should always
+ // be reported as validated, but other checks still need to be
+ // done. For example, it should still validate strict private DNS and
+ // show a notification if not available, because the network will
+ // be unusable for this additional reason.
+ mEvaluationState.setCaptivePortalWantedAsIs();
+ // A successful evaluation result should be reported immediately, so
+ // that the network stack may immediately use the validation in ranking
+ // without waiting for a possibly long private DNS or bandwidth eval
+ // step.
+ mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_VALID,
+ null);
// TODO: Distinguish this from a network that actually validates.
// Displaying the "x" on the system UI icon may still be a good idea.
transitionTo(mEvaluatingPrivateDnsState);
@@ -984,12 +1046,29 @@
break;
case EVENT_NETWORK_CAPABILITIES_CHANGED:
mNetworkCapabilities = (NetworkCapabilities) message.obj;
+ suppressNotificationIfNetworkRestricted();
+ break;
+ case EVENT_RESOURCE_CONFIG_CHANGED:
+ // RRO generation does not happen during package installation and instead after
+ // the OMS receives the PACKAGE_ADDED event, there is a delay where the old
+ // idmap is used with the new target package resulting in the incorrect overlay
+ // is used. Renew the resource if a configuration change is received.
+ // TODO: Remove it once design to generate the idmaps during package
+ // installation in overlay manager and package manager is ready.
+ if (checkAndRenewResourceConfig()) {
+ sendMessage(CMD_FORCE_REEVALUATION, NO_UID, 1 /* forceAccept */);
+ }
break;
default:
break;
}
return HANDLED;
}
+
+ @Override
+ public void exit() {
+ mContext.unregisterReceiver(mConfigurationReceiver);
+ }
}
// Being in the ValidatedState State indicates a Network is:
@@ -1227,6 +1306,22 @@
if (!mEvaluationTimer.isStarted()) {
mEvaluationTimer.start();
}
+
+ // Check if the network is captive with Terms & Conditions page. The first network
+ // evaluation for captive networks with T&Cs returns early but NetworkMonitor will then
+ // keep checking for connectivity to determine when the T&Cs are cleared.
+ if (isTermsAndConditionsCaptive(mInfoShim.getCaptivePortalData(mLinkProperties))
+ && mValidations == 0) {
+ mLastPortalProbeResult = new CaptivePortalProbeResult(
+ CaptivePortalProbeResult.PORTAL_CODE,
+ mLinkProperties.getCaptivePortalData().getUserPortalUrl()
+ .toString(), null,
+ CaptivePortalProbeResult.PROBE_UNKNOWN);
+ mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,
+ mLastPortalProbeResult.redirectUrl);
+ transitionTo(mCaptivePortalState);
+ return;
+ }
sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
if (mUidResponsibleForReeval != INVALID_UID) {
TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
@@ -1264,11 +1359,19 @@
// the network so don't bother validating here. Furthermore sending HTTP
// packets over the network may be undesirable, for example an extremely
// expensive metered network, or unwanted leaking of the User Agent string.
+ // Also don't bother validating networks that the user already said they
+ // wanted as-is.
//
// On networks that need to support private DNS in strict mode (e.g., VPNs, but
// not networks that don't provide Internet access), we still need to perform
// private DNS server resolution.
- if (!isValidationRequired()) {
+ if (mEvaluationState.isCaptivePortalWantedAsIs()
+ && isPrivateDnsValidationRequired()) {
+ // Captive portals can only be detected on networks that validate both
+ // validation and private DNS validation.
+ validationLog("Captive portal is used as is, resolving private DNS");
+ transitionTo(mEvaluatingPrivateDnsState);
+ } else if (!isValidationRequired()) {
if (isPrivateDnsValidationRequired()) {
validationLog("Network would not satisfy default request, "
+ "resolving private DNS");
@@ -1286,7 +1389,9 @@
return HANDLED;
case CMD_FORCE_REEVALUATION:
// The evaluation process restarts via EvaluatingState#enter.
- return shouldAcceptForceRevalidation() ? NOT_HANDLED : HANDLED;
+ final boolean forceAccept = (message.arg2 != 0);
+ return forceAccept || shouldAcceptForceRevalidation()
+ ? NOT_HANDLED : HANDLED;
// Disable HTTPS probe and transition to EvaluatingPrivateDnsState because:
// 1. Network is connected and finish the network validation.
// 2. NetworkMonitor detects network is partial connectivity and user accepts it.
@@ -1538,8 +1643,13 @@
final int token = ++mProbeToken;
final ValidationProperties deps = new ValidationProperties(mNetworkCapabilities);
+ final URL fallbackUrl = nextFallbackUrl();
+ final URL[] httpsUrls = Arrays.copyOf(
+ mCaptivePortalHttpsUrls, mCaptivePortalHttpsUrls.length);
+ final URL[] httpUrls = Arrays.copyOf(
+ mCaptivePortalHttpUrls, mCaptivePortalHttpUrls.length);
mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE, token, 0,
- isCaptivePortal(deps))));
+ isCaptivePortal(deps, httpsUrls, httpUrls, fallbackUrl))));
mThread.start();
}
@@ -1562,6 +1672,16 @@
// Transit EvaluatingPrivateDnsState to get to Validated
// state (even if no Private DNS validation required).
transitionTo(mEvaluatingPrivateDnsState);
+ } else if (isTermsAndConditionsCaptive(
+ mInfoShim.getCaptivePortalData(mLinkProperties))) {
+ mLastPortalProbeResult = new CaptivePortalProbeResult(
+ CaptivePortalProbeResult.PORTAL_CODE,
+ mLinkProperties.getCaptivePortalData().getUserPortalUrl()
+ .toString(), null,
+ CaptivePortalProbeResult.PROBE_UNKNOWN);
+ mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,
+ mLastPortalProbeResult.redirectUrl);
+ transitionTo(mCaptivePortalState);
} else if (probeResult.isPortal()) {
mEvaluationState.reportEvaluationResult(NETWORK_VALIDATION_RESULT_INVALID,
probeResult.redirectUrl);
@@ -1919,18 +2039,24 @@
}
final long now = System.currentTimeMillis();
- if (expTime < now || (expTime - now) > TEST_URL_EXPIRATION_MS) return null;
+ if (expTime < now || (expTime - now) > TEST_URL_EXPIRATION_MS) {
+ logw("Skipping test URL with expiration " + expTime + ", now " + now);
+ return null;
+ }
final String strUrl = mDependencies.getDeviceConfigProperty(NAMESPACE_CONNECTIVITY,
key, null /* defaultValue */);
- if (!isValidTestUrl(strUrl)) return null;
+ if (!isValidTestUrl(strUrl)) {
+ logw("Skipping invalid test URL " + strUrl);
+ return null;
+ }
return makeURL(strUrl);
}
- private String getCaptivePortalServerHttpsUrl() {
- return getSettingFromResource(mCustomizedContext,
- R.string.config_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL,
- mCustomizedContext.getResources().getString(
+ private String getCaptivePortalServerHttpsUrl(@NonNull Context context) {
+ return getSettingFromResource(context,
+ R.string.config_captive_portal_https_url, mCaptivePortalHttpsUrlFromSetting,
+ context.getResources().getString(
R.string.default_captive_portal_https_url));
}
@@ -2007,10 +2133,10 @@
* it has its own updatable strategies to detect captive portals. The framework only advises
* on one URL that can be used, while NetworkMonitor may implement more complex logic.
*/
- public String getCaptivePortalServerHttpUrl() {
- return getSettingFromResource(mCustomizedContext,
- R.string.config_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL,
- mCustomizedContext.getResources().getString(
+ public String getCaptivePortalServerHttpUrl(@NonNull Context context) {
+ return getSettingFromResource(context,
+ R.string.config_captive_portal_http_url, mCaptivePortalHttpUrlFromSetting,
+ context.getResources().getString(
R.string.default_captive_portal_http_url));
}
@@ -2046,13 +2172,13 @@
}
@VisibleForTesting
- URL[] makeCaptivePortalFallbackUrls() {
+ URL[] makeCaptivePortalFallbackUrls(@NonNull Context context) {
try {
final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL,
null);
final URL[] settingProviderUrls =
combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS);
- return getProbeUrlArrayConfig(settingProviderUrls,
+ return getProbeUrlArrayConfig(context, settingProviderUrls,
R.array.config_captive_portal_fallback_urls,
R.array.default_captive_portal_fallback_urls,
this::makeURL);
@@ -2063,7 +2189,7 @@
}
}
- private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs() {
+ private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs(@NonNull Context context) {
try {
final String settingsValue = mDependencies.getDeviceConfigProperty(
NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
@@ -2073,7 +2199,7 @@
? emptySpecs
: parseCaptivePortalProbeSpecs(settingsValue).toArray(emptySpecs);
- return getProbeUrlArrayConfig(providerValue,
+ return getProbeUrlArrayConfig(context, providerValue,
R.array.config_captive_portal_fallback_probe_specs,
DEFAULT_CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS,
CaptivePortalProbeSpec::parseSpecOrNull);
@@ -2084,17 +2210,17 @@
}
}
- private URL[] makeCaptivePortalHttpsUrls() {
+ private URL[] makeCaptivePortalHttpsUrls(@NonNull Context context) {
final URL testUrl = getTestUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL);
if (testUrl != null) return new URL[] { testUrl };
- final String firstUrl = getCaptivePortalServerHttpsUrl();
+ final String firstUrl = getCaptivePortalServerHttpsUrl(context);
try {
final URL[] settingProviderUrls =
combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTPS_URLS);
// firstUrl will at least be default configuration, so default value in
// getProbeUrlArrayConfig is actually never used.
- return getProbeUrlArrayConfig(settingProviderUrls,
+ return getProbeUrlArrayConfig(context, settingProviderUrls,
R.array.config_captive_portal_https_urls,
DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS, this::makeURL);
} catch (Exception e) {
@@ -2105,17 +2231,17 @@
}
}
- private URL[] makeCaptivePortalHttpUrls() {
+ private URL[] makeCaptivePortalHttpUrls(@NonNull Context context) {
final URL testUrl = getTestUrl(TEST_CAPTIVE_PORTAL_HTTP_URL);
if (testUrl != null) return new URL[] { testUrl };
- final String firstUrl = getCaptivePortalServerHttpUrl();
+ final String firstUrl = getCaptivePortalServerHttpUrl(context);
try {
final URL[] settingProviderUrls =
combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_HTTP_URLS);
// firstUrl will at least be default configuration, so default value in
// getProbeUrlArrayConfig is actually never used.
- return getProbeUrlArrayConfig(settingProviderUrls,
+ return getProbeUrlArrayConfig(context, settingProviderUrls,
R.array.config_captive_portal_http_urls,
DEFAULT_CAPTIVE_PORTAL_HTTP_URLS, this::makeURL);
} catch (Exception e) {
@@ -2143,21 +2269,20 @@
* <p>The configuration resource is prioritized, then the provider value.
* @param context The context
* @param configResource The resource id for the configuration parameter
- * @param symbol The symbol in the settings provider
+ * @param settingValue The value in the settings provider
* @param defaultValue The default value
* @return The best available value
*/
@Nullable
private String getSettingFromResource(@NonNull final Context context,
- @StringRes int configResource, @NonNull String symbol, @NonNull String defaultValue) {
+ @StringRes int configResource, @NonNull String settingValue,
+ @NonNull String defaultValue) {
final Resources res = context.getResources();
String setting = res.getString(configResource);
if (!TextUtils.isEmpty(setting)) return setting;
- setting = mDependencies.getSetting(context, symbol, null);
-
- if (!TextUtils.isEmpty(setting)) return setting;
+ if (!TextUtils.isEmpty(settingValue)) return settingValue;
return defaultValue;
}
@@ -2167,17 +2292,20 @@
*
* <p>The configuration resource is prioritized, then the provider values, then the default
* resource values.
+ *
+ * @param context The Context
* @param providerValue Values obtained from the setting provider.
* @param configResId ID of the configuration resource.
* @param defaultResId ID of the default resource.
* @param resourceConverter Converter from the resource strings to stored setting class. Null
* return values are ignored.
*/
- private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId,
- @ArrayRes int defaultResId, @NonNull Function<String, T> resourceConverter) {
- final Resources res = mCustomizedContext.getResources();
- return getProbeUrlArrayConfig(providerValue, configResId, res.getStringArray(defaultResId),
- resourceConverter);
+ private <T> T[] getProbeUrlArrayConfig(@NonNull Context context, @NonNull T[] providerValue,
+ @ArrayRes int configResId, @ArrayRes int defaultResId,
+ @NonNull Function<String, T> resourceConverter) {
+ final Resources res = context.getResources();
+ return getProbeUrlArrayConfig(context, providerValue, configResId,
+ res.getStringArray(defaultResId), resourceConverter);
}
/**
@@ -2185,15 +2313,18 @@
*
* <p>The configuration resource is prioritized, then the provider values, then the default
* resource values.
+ *
+ * @param context The Context
* @param providerValue Values obtained from the setting provider.
* @param configResId ID of the configuration resource.
* @param defaultConfig Values of default configuration.
* @param resourceConverter Converter from the resource strings to stored setting class. Null
* return values are ignored.
*/
- private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId,
- String[] defaultConfig, @NonNull Function<String, T> resourceConverter) {
- final Resources res = mCustomizedContext.getResources();
+ private <T> T[] getProbeUrlArrayConfig(@NonNull Context context, @NonNull T[] providerValue,
+ @ArrayRes int configResId, String[] defaultConfig,
+ @NonNull Function<String, T> resourceConverter) {
+ final Resources res = context.getResources();
String[] configValue = res.getStringArray(configResId);
if (configValue.length == 0) {
@@ -2272,15 +2403,14 @@
}
}
- private CaptivePortalProbeResult isCaptivePortal(ValidationProperties properties) {
+ private CaptivePortalProbeResult isCaptivePortal(ValidationProperties properties,
+ URL[] httpsUrls, URL[] httpUrls, URL fallbackUrl) {
if (!mIsCaptivePortalCheckEnabled) {
validationLog("Validation disabled.");
return CaptivePortalProbeResult.success(CaptivePortalProbeResult.PROBE_UNKNOWN);
}
URL pacUrl = null;
- final URL[] httpsUrls = mCaptivePortalHttpsUrls;
- final URL[] httpUrls = mCaptivePortalHttpUrls;
// On networks with a PAC instead of fetching a URL that should result in a 204
// response, we instead simply fetch the PAC script. This is done for a few reasons:
@@ -2321,7 +2451,7 @@
} else if (mUseHttps && httpsUrls.length == 1 && httpUrls.length == 1) {
// Probe results are reported inside sendHttpAndHttpsParallelWithFallbackProbes.
result = sendHttpAndHttpsParallelWithFallbackProbes(properties, proxyInfo,
- httpsUrls[0], httpUrls[0]);
+ httpsUrls[0], httpUrls[0], fallbackUrl);
} else if (mUseHttps) {
// Support result aggregation from multiple Urls.
result = sendMultiParallelHttpAndHttpsProbes(properties, proxyInfo, httpsUrls,
@@ -2333,10 +2463,6 @@
long endTime = SystemClock.elapsedRealtime();
- sendNetworkConditionsBroadcast(true /* response received */,
- result.isPortal() /* isCaptivePortal */,
- startTime, endTime);
-
log("isCaptivePortal: isSuccessful()=" + result.isSuccessful()
+ " isPortal()=" + result.isPortal()
+ " RedirectUrl=" + result.redirectUrl
@@ -2433,7 +2559,7 @@
String redirectUrl = null;
final Stopwatch probeTimer = new Stopwatch().start();
final int oldTag = TrafficStats.getAndSetThreadStatsTag(
- TrafficStatsConstants.TAG_SYSTEM_PROBE);
+ NetworkStackConstants.TAG_SYSTEM_PROBE);
try {
// Follow redirects for PAC probes as such probes verify connectivity by fetching the
// PAC proxy file, which may be configured behind a redirect.
@@ -2519,8 +2645,17 @@
final CaptivePortalProbeResult probeResult;
if (probeSpec == null) {
+ if (CaptivePortalProbeResult.isPortalCode(httpResponseCode)
+ && TextUtils.isEmpty(redirectUrl)
+ && ShimUtils.isAtLeastS()) {
+ // If a portal is a non-redirect portal (often portals that return HTTP 200 with a
+ // login page for all HTTP requests), report the probe URL as the login URL starting
+ // from S (b/172048052). This avoids breaking assumptions that
+ // [is a portal] is equivalent to [there is a login URL].
+ redirectUrl = url.toString();
+ }
probeResult = new CaptivePortalProbeResult(httpResponseCode, redirectUrl,
- url.toString(), 1 << probeType);
+ url.toString(), 1 << probeType);
} else {
probeResult = probeSpec.getResult(httpResponseCode, redirectUrl);
}
@@ -2918,7 +3053,8 @@
}
private CaptivePortalProbeResult sendHttpAndHttpsParallelWithFallbackProbes(
- ValidationProperties properties, ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
+ ValidationProperties properties, ProxyInfo proxy, URL httpsUrl, URL httpUrl,
+ URL fallbackUrl) {
// Number of probes to wait for. If a probe completes with a conclusive answer
// it shortcuts the latch immediately by forcing the count to 0.
final CountDownLatch latch = new CountDownLatch(2);
@@ -2964,10 +3100,10 @@
// If a fallback method exists, use it to retry portal detection.
// If we have new-style probe specs, use those. Otherwise, use the fallback URLs.
final CaptivePortalProbeSpec probeSpec = nextFallbackSpec();
- final URL fallbackUrl = (probeSpec != null) ? probeSpec.getUrl() : nextFallbackUrl();
+ final URL fallback = (probeSpec != null) ? probeSpec.getUrl() : fallbackUrl;
CaptivePortalProbeResult fallbackProbeResult = null;
- if (fallbackUrl != null) {
- fallbackProbeResult = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
+ if (fallback != null) {
+ fallbackProbeResult = sendHttpProbe(fallback, PROBE_FALLBACK, probeSpec);
reportHttpProbeResult(NETWORK_VALIDATION_PROBE_FALLBACK, fallbackProbeResult);
if (fallbackProbeResult.isPortal()) {
return fallbackProbeResult;
@@ -3006,74 +3142,6 @@
return null;
}
- /**
- * @param responseReceived - whether or not we received a valid HTTP response to our request.
- * If false, isCaptivePortal and responseTimestampMs are ignored
- * TODO: This should be moved to the transports. The latency could be passed to the transports
- * along with the captive portal result. Currently the TYPE_MOBILE broadcasts appear unused so
- * perhaps this could just be added to the WiFi transport only.
- */
- private void sendNetworkConditionsBroadcast(boolean responseReceived, boolean isCaptivePortal,
- long requestTimestampMs, long responseTimestampMs) {
- Intent latencyBroadcast =
- new Intent(NetworkMonitorUtils.ACTION_NETWORK_CONDITIONS_MEASURED);
- if (mNetworkCapabilities.hasTransport(TRANSPORT_WIFI)) {
- if (!mWifiManager.isScanAlwaysAvailable()) {
- return;
- }
-
- WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
- if (currentWifiInfo != null) {
- // NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
- // surrounded by double quotation marks (thus violating the Javadoc), but this
- // was changed to match the Javadoc in API 17. Since clients may have started
- // sanitizing the output of this method since API 17 was released, we should
- // not change it here as it would become impossible to tell whether the SSID is
- // simply being surrounded by quotes due to the API, or whether those quotes
- // are actually part of the SSID.
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_SSID,
- currentWifiInfo.getSSID());
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_BSSID,
- currentWifiInfo.getBSSID());
- } else {
- if (VDBG) logw("network info is TYPE_WIFI but no ConnectionInfo found");
- return;
- }
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_WIFI);
- } else if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
- // TODO(b/123893112): Support multi-sim.
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_NETWORK_TYPE,
- mTelephonyManager.getNetworkType());
- final ServiceState dataSs = mTelephonyManager.getServiceState();
- if (dataSs == null) {
- logw("failed to retrieve ServiceState");
- return;
- }
- // See if the data sub is registered for PS services on cell.
- final NetworkRegistrationInfo nri = dataSs.getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- latencyBroadcast.putExtra(
- NetworkMonitorUtils.EXTRA_CELL_ID,
- nri == null ? null : nri.getCellIdentity());
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_CONNECTIVITY_TYPE, TYPE_MOBILE);
- } else {
- return;
- }
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_RESPONSE_RECEIVED,
- responseReceived);
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_REQUEST_TIMESTAMP_MS,
- requestTimestampMs);
-
- if (responseReceived) {
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_IS_CAPTIVE_PORTAL,
- isCaptivePortal);
- latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_RESPONSE_TIMESTAMP_MS,
- responseTimestampMs);
- }
- mDependencies.sendNetworkConditionsBroadcast(mContext, latencyBroadcast);
- }
-
private void logNetworkEvent(int evtype) {
int[] transports = mNetworkCapabilities.getTransportTypes();
mMetricsLog.log(mCleartextDnsNetwork, transports, new NetworkEvent(evtype));
@@ -3186,15 +3254,6 @@
}
/**
- * Send a broadcast indicating network conditions.
- */
- public void sendNetworkConditionsBroadcast(@NonNull Context context,
- @NonNull Intent broadcast) {
- context.sendBroadcastAsUser(broadcast, UserHandle.CURRENT,
- NetworkMonitorUtils.PERMISSION_ACCESS_NETWORK_CONDITIONS);
- }
-
- /**
* Check whether or not one specific experimental feature for a particular namespace from
* {@link DeviceConfig} is enabled by comparing NetworkStack module version
* {@link NetworkStack} with current version of property. If this property version is valid,
@@ -3216,7 +3275,7 @@
* data to statsd pipeline.
* @param stats a {@link DataStallDetectionStats} that contains the detection level
* information.
- * @para result the network reevaluation result.
+ * @param result the network reevaluation result.
*/
public void writeDataStallDetectionStats(@NonNull final DataStallDetectionStats stats,
@NonNull final CaptivePortalProbeResult result) {
@@ -3277,6 +3336,10 @@
// considered in the evaluation happened in defined threshold time.
final long now = SystemClock.elapsedRealtime();
final long firstTimeoutTime = now - mDnsEvents[firstConsecutiveTimeoutIndex].mTimeStamp;
+ if (DDBG_STALL) {
+ Log.d(TAG, "DSD.isDataStallSuspected, first="
+ + firstTimeoutTime + ", valid=" + validTime);
+ }
return (firstTimeoutTime < validTime);
}
@@ -3331,12 +3394,17 @@
int typeToCollect = 0;
final int notStall = -1;
- final StringJoiner msg = (DBG || VDBG_STALL) ? new StringJoiner(", ") : null;
+ final StringJoiner msg = (DBG || VDBG_STALL || DDBG_STALL) ? new StringJoiner(", ") : null;
// Reevaluation will generate traffic. Thus, set a minimal reevaluation timer to limit the
// possible traffic cost in metered network.
+ final long currentTime = SystemClock.elapsedRealtime();
if (!mNetworkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
- && (SystemClock.elapsedRealtime() - getLastProbeTime()
- < mDataStallMinEvaluateTime)) {
+ && (currentTime - getLastProbeTime() < mDataStallMinEvaluateTime)) {
+ if (DDBG_STALL) {
+ Log.d(TAG, "isDataStall: false, currentTime=" + currentTime
+ + ", lastProbeTime=" + getLastProbeTime()
+ + ", MinEvaluateTime=" + mDataStallMinEvaluateTime);
+ }
return false;
}
// Check TCP signal. Suspect it may be a data stall if :
@@ -3349,7 +3417,7 @@
} else if (tst.isDataStallSuspected()) {
typeToCollect |= DATA_STALL_EVALUATION_TYPE_TCP;
}
- if (DBG || VDBG_STALL) {
+ if (DBG || VDBG_STALL || DDBG_STALL) {
msg.add("tcp packets received=" + tst.getLatestReceivedCount())
.add("latest tcp fail rate=" + tst.getLatestPacketFailPercentage());
}
@@ -3366,7 +3434,7 @@
typeToCollect |= DATA_STALL_EVALUATION_TYPE_DNS;
logNetworkEvent(NetworkEvent.NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND);
}
- if (DBG || VDBG_STALL) {
+ if (DBG || VDBG_STALL || DDBG_STALL) {
msg.add("consecutive dns timeout count=" + dsd.getConsecutiveTimeoutCount());
}
}
@@ -3391,7 +3459,7 @@
}
// log only data stall suspected.
- if ((DBG && (typeToCollect > 0)) || VDBG_STALL) {
+ if ((DBG && (typeToCollect > 0)) || VDBG_STALL || DDBG_STALL) {
log("isDataStall: result=" + typeToCollect + ", " + msg);
}
@@ -3417,18 +3485,28 @@
// NETWORK_VALIDATION_RESULT_VALID. But with this scheme, the first two or three validation
// reports are all failures, because they are "HTTP succeeded but validation not yet passed",
// "HTTP and HTTPS succeeded but validation not yet passed", etc.
+ // TODO : rename EvaluationState to not contain "State" in the name, as it makes this class
+ // sound like one of the states of the state machine, which it's not.
@VisibleForTesting
protected class EvaluationState {
// The latest validation result for this network. This is a bitmask of
// INetworkMonitor.NETWORK_VALIDATION_RESULT_* constants.
private int mEvaluationResult = NETWORK_VALIDATION_RESULT_INVALID;
+
+
+ // Set when the captive portal app said this network should be used as is as a result
+ // of user interaction. The valid bit represents the user's decision to override automatic
+ // determination of whether the network has access to Internet, so in this case the
+ // network is always reported as validated.
+ // TODO : Make ConnectivityService aware of this state, so that it can use the network as
+ // the default without setting the VALIDATED bit, as it's a bit of a lie. This can't be
+ // done on Android <= R where CS can't be updated, but it is doable on S+.
+ private boolean mCaptivePortalWantedAsIs = false;
// Indicates which probes have succeeded since clearProbeResults was called.
// This is a bitmask of INetworkMonitor.NETWORK_VALIDATION_PROBE_* constants.
private int mProbeResults = 0;
// A bitmask to record which probes are completed.
private int mProbeCompleted = 0;
- // The latest redirect URL.
- private String mRedirectUrl;
protected void clearProbeResults() {
mProbeResults = 0;
@@ -3462,9 +3540,26 @@
});
}
+ protected void setCaptivePortalWantedAsIs() {
+ mCaptivePortalWantedAsIs = true;
+ }
+
+ protected boolean isCaptivePortalWantedAsIs() {
+ return mCaptivePortalWantedAsIs;
+ }
+
protected void reportEvaluationResult(int result, @Nullable String redirectUrl) {
+ if (mCaptivePortalWantedAsIs) {
+ result = NETWORK_VALIDATION_RESULT_VALID;
+ } else if (!isValidationRequired() && mProbeCompleted == 0 && mCallbackVersion >= 11) {
+ // If validation is not required AND no probes were attempted, the validation was
+ // skipped. Report this to ConnectivityService for ConnectivityDiagnostics, but only
+ // if the platform has callback version 11+, as ConnectivityService must also know
+ // how to understand this bit.
+ result |= NETWORK_VALIDATION_RESULT_SKIPPED;
+ }
+
mEvaluationResult = result;
- mRedirectUrl = redirectUrl;
final NetworkTestResultParcelable p = new NetworkTestResultParcelable();
p.result = result;
p.probesSucceeded = mProbeResults;
@@ -3566,4 +3661,50 @@
private static Uri getCaptivePortalApiUrl(LinkProperties lp) {
return NetworkInformationShimImpl.newInstance().getCaptivePortalApiUrl(lp);
}
+
+ /**
+ * Check if the network is captive with terms and conditions page
+ * @return true if network is captive with T&C page, false otherwise
+ */
+ private boolean isTermsAndConditionsCaptive(CaptivePortalDataShim captivePortalDataShim) {
+ return captivePortalDataShim != null
+ && captivePortalDataShim.getUserPortalUrl() != null
+ && !TextUtils.isEmpty(captivePortalDataShim.getUserPortalUrl().toString())
+ && captivePortalDataShim.isCaptive()
+ && captivePortalDataShim.getUserPortalUrlSource()
+ == ConstantsShim.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT;
+ }
+
+ private boolean checkAndRenewResourceConfig() {
+ boolean reevaluationNeeded = false;
+
+ final Context customizedContext = getCustomizedContextOrDefault();
+ final URL[] captivePortalHttpsUrls = makeCaptivePortalHttpsUrls(customizedContext);
+ if (!Arrays.equals(mCaptivePortalHttpsUrls, captivePortalHttpsUrls)) {
+ mCaptivePortalHttpsUrls = captivePortalHttpsUrls;
+ reevaluationNeeded = true;
+ log("checkAndRenewResourceConfig: update captive portal https urls to "
+ + Arrays.toString(mCaptivePortalHttpsUrls));
+ }
+
+ final URL[] captivePortalHttpUrls = makeCaptivePortalHttpUrls(customizedContext);
+ if (!Arrays.equals(mCaptivePortalHttpUrls, captivePortalHttpUrls)) {
+ mCaptivePortalHttpUrls = captivePortalHttpUrls;
+ reevaluationNeeded = true;
+ log("checkAndRenewResourceConfig: update captive portal http urls to "
+ + Arrays.toString(mCaptivePortalHttpUrls));
+ }
+
+ final URL[] captivePortalFallbackUrls = makeCaptivePortalFallbackUrls(customizedContext);
+ if (!Arrays.equals(mCaptivePortalFallbackUrls, captivePortalFallbackUrls)) {
+ mCaptivePortalFallbackUrls = captivePortalFallbackUrls;
+ // Reset the index since the array is changed.
+ mNextFallbackUrlIndex = 0;
+ reevaluationNeeded = true;
+ log("checkAndRenewResourceConfig: update captive portal fallback urls to"
+ + Arrays.toString(mCaptivePortalFallbackUrls));
+ }
+
+ return reevaluationNeeded;
+ }
}
diff --git a/tests/hostdriven/Android.bp b/tests/hostdriven/Android.bp
index 3509f89..6c3de45 100644
--- a/tests/hostdriven/Android.bp
+++ b/tests/hostdriven/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_test_host {
name: "NetworkStackHostTests",
srcs: ["host/src/**/*.kt"],
diff --git a/tests/hostlib/Android.bp b/tests/hostlib/Android.bp
index 9a88634..189a88c 100644
--- a/tests/hostlib/Android.bp
+++ b/tests/hostlib/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_library_host {
name: "net-host-tests-utils",
srcs: [
@@ -26,4 +30,4 @@
"kotlin-test",
"cts-install-lib-host",
],
-}
\ No newline at end of file
+}
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index 2c30b3c..9137c5c 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_defaults {
name: "NetworkStackIntegrationTestsJniDefaults",
defaults: ["libnetworkstackutilsjni_deps"],
@@ -46,7 +50,6 @@
"android.test.base",
"android.test.mock",
],
- jarjar_rules: ":NetworkStackJarJarRules",
visibility: ["//visibility:private"],
}
@@ -68,6 +71,8 @@
platform_apis: true,
test_suites: ["device-tests"],
min_sdk_version: "29",
+ target_sdk_version: "30",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
// Network stack next integration tests.
@@ -83,22 +88,7 @@
certificate: "networkstack",
platform_apis: true,
test_suites: ["device-tests"],
- enabled: false, // Disabled in mainline-prod
-}
-
-// The static lib needs to be jarjared by each module so they do not conflict with each other
-// (e.g. wifi, system server, network stack need to use different package names when including it).
-// Apply NetworkStack jarjar rules to the tests as well so classes in NetworkStaticLibTests have the
-// same package names as in module code.
-android_library {
- name: "NetworkStackStaticLibTestsLib",
- platform_apis: true,
- min_sdk_version: "29",
jarjar_rules: ":NetworkStackJarJarRules",
- static_libs: [
- "NetworkStaticLibTestsLib",
- "NetdStaticLibTestsLib",
- ],
}
// Special version of the network stack tests that includes all tests necessary for code coverage
@@ -108,14 +98,18 @@
certificate: "networkstack",
platform_apis: true,
min_sdk_version: "29",
+ target_sdk_version: "30",
test_suites: ["device-tests", "mts"],
test_config: "AndroidTest_Coverage.xml",
defaults: ["NetworkStackIntegrationTestsJniDefaults"],
static_libs: [
+ "modules-utils-native-coverage-listener",
"NetworkStackTestsLib",
"NetworkStackIntegrationTestsLib",
- "NetworkStackStaticLibTestsLib",
+ "NetworkStaticLibTestsLib",
+ "NetdStaticLibTestsLib",
],
compile_multilib: "both",
manifest: "AndroidManifest_coverage.xml",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
diff --git a/tests/integration/AndroidManifest.xml b/tests/integration/AndroidManifest.xml
index 12f5d7d..bfd3735 100644
--- a/tests/integration/AndroidManifest.xml
+++ b/tests/integration/AndroidManifest.xml
@@ -16,7 +16,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.networkstack.integrationtests"
android:sharedUserId="android.uid.networkstack">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<!-- Note: do not add any privileged or signature permissions that are granted
to the network stack app. Otherwise, the test APK will install, but when the device is
diff --git a/tests/integration/AndroidManifest_coverage.xml b/tests/integration/AndroidManifest_coverage.xml
index 660e42d..fc91e59 100644
--- a/tests/integration/AndroidManifest_coverage.xml
+++ b/tests/integration/AndroidManifest_coverage.xml
@@ -16,7 +16,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.networkstack.coverage"
android:sharedUserId="android.uid.networkstack">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<!-- Note: do not add any privileged or signature permissions that are granted
to the network stack app. Otherwise, the test APK will install, but when the device is
diff --git a/tests/integration/AndroidTest_Coverage.xml b/tests/integration/AndroidTest_Coverage.xml
index e33fa87..3e7361b 100644
--- a/tests/integration/AndroidTest_Coverage.xml
+++ b/tests/integration/AndroidTest_Coverage.xml
@@ -23,5 +23,6 @@
<option name="package" value="com.android.server.networkstack.coverage" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
+ <option name="device-listeners" value="com.android.modules.utils.testing.NativeCoverageHackInstrumentationListener" />
</test>
</configuration>
diff --git a/tests/integration/lint-baseline.xml b/tests/integration/lint-baseline.xml
new file mode 100644
index 0000000..eadec6f
--- /dev/null
+++ b/tests/integration/lint-baseline.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getDhcpServerAddress`"
+ errorLine1=" assertEquals(SERVER_ADDR, captor.getValue().getDhcpServerAddress());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java"
+ line="1327"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" argThat(lp -> Objects.equals(expected, lp.getNat64Prefix())));"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java"
+ line="1623"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" lp -> !Objects.equals(unchanged, lp.getNat64Prefix())));"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java"
+ line="1629"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" if (lp.getNat64Prefix() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java"
+ line="1660"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
+ errorLine1=" assertEquals(prefix, lp.getNat64Prefix());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java"
+ line="1661"
+ column="37"/>
+ </issue>
+
+</issues>
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt b/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
index 9f29a2e..748ee5a 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
@@ -17,7 +17,14 @@
package android.net.ip
import android.net.ipmemorystore.NetworkAttributes
+import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener
+import android.net.ipmemorystore.Status
+import android.net.ipmemorystore.Status.SUCCESS
+import android.util.ArrayMap
+import java.net.Inet6Address
+import kotlin.test.assertEquals
import org.mockito.Mockito.any
+import org.mockito.Mockito.doAnswer
import org.mockito.ArgumentCaptor
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
@@ -28,22 +35,20 @@
* Tests for IpClient, run with signature permissions.
*/
class IpClientIntegrationTest : IpClientIntegrationTestCommon() {
+ private val mEnabledFeatures = ArrayMap<String, Boolean>()
+
override fun makeIIpClient(ifaceName: String, cb: IIpClientCallbacks): IIpClient {
return mIpc.makeConnector()
}
override fun useNetworkStackSignature() = true
- override fun setDhcpFeatures(
- isDhcpLeaseCacheEnabled: Boolean,
- isRapidCommitEnabled: Boolean,
- isDhcpIpConflictDetectEnabled: Boolean,
- isIPv6OnlyPreferredEnabled: Boolean
- ) {
- mDependencies.setDhcpLeaseCacheEnabled(isDhcpLeaseCacheEnabled)
- mDependencies.setDhcpRapidCommitEnabled(isRapidCommitEnabled)
- mDependencies.setDhcpIpConflictDetectEnabled(isDhcpIpConflictDetectEnabled)
- mDependencies.setIPv6OnlyPreferredEnabled(isIPv6OnlyPreferredEnabled)
+ override fun isFeatureEnabled(name: String, defaultEnabled: Boolean): Boolean {
+ return mEnabledFeatures.get(name) ?: defaultEnabled
+ }
+
+ override fun setFeatureEnabled(name: String, enabled: Boolean) {
+ mEnabledFeatures.put(name, enabled)
}
override fun getStoredNetworkAttributes(l2Key: String, timeout: Long): NetworkAttributes {
@@ -57,4 +62,23 @@
override fun assertIpMemoryNeverStoreNetworkAttributes(l2Key: String, timeout: Long) {
verify(mIpMemoryStore, never()).storeNetworkAttributes(eq(l2Key), any(), any())
}
+
+ override fun assertNotifyNeighborLost(targetIp: Inet6Address) {
+ val target = ArgumentCaptor.forClass(Inet6Address::class.java)
+
+ verify(mCallback, timeout(TEST_TIMEOUT_MS)).notifyLost(target.capture(), any())
+ assertEquals(targetIp, target.getValue())
+ }
+
+ override fun assertNeverNotifyNeighborLost() {
+ verify(mCallback, never()).notifyLost(any(), any())
+ }
+
+ override fun storeNetworkAttributes(l2Key: String, na: NetworkAttributes) {
+ doAnswer { inv ->
+ val listener = inv.getArgument<OnNetworkAttributesRetrievedListener>(1)
+ listener.onNetworkAttributesRetrieved(Status(SUCCESS), l2Key, na)
+ true
+ }.`when`(mIpMemoryStore).retrieveNetworkAttributes(eq(l2Key), any())
+ }
}
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
index 1b5660c..6ade54f 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
@@ -27,31 +27,37 @@
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
import static android.net.dhcp.DhcpPacket.MIN_V6ONLY_WAIT_MS;
import static android.net.dhcp.DhcpResultsParcelableUtil.fromStableParcelable;
+import static android.net.ip.IpReachabilityMonitor.MIN_NUD_SOLICIT_NUM;
+import static android.net.ip.IpReachabilityMonitor.NUD_MCAST_RESOLICIT_NUM;
import static android.net.ipmemorystore.Status.SUCCESS;
+import static android.net.shared.ProvisioningConfiguration.VERSION_ADDED_PROVISIONING_ENUM;
import static android.system.OsConstants.ETH_P_IPV6;
import static android.system.OsConstants.IFA_F_TEMPORARY;
import static android.system.OsConstants.IPPROTO_ICMPV6;
-import static android.system.OsConstants.IPPROTO_TCP;
import static com.android.net.module.util.Inet4AddressUtils.getBroadcastAddress;
import static com.android.net.module.util.Inet4AddressUtils.getPrefixMaskAsInet4Address;
import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY;
import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST;
import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN;
+import static com.android.net.module.util.NetworkStackConstants.ETHER_BROADCAST;
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
-import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_CHECKSUM_OFFSET;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_LENGTH_SCALING_FACTOR;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_PIO;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_RDNSS;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_RA_HEADER_LEN;
-import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;
import static com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
-import static com.android.net.module.util.NetworkStackConstants.IPV6_LEN_OFFSET;
import static com.android.net.module.util.NetworkStackConstants.IPV6_PROTOCOL_OFFSET;
+import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE;
+import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER;
+import static com.android.net.module.util.NetworkStackConstants.NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED;
+import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_AUTONOMOUS;
+import static com.android.net.module.util.NetworkStackConstants.PIO_FLAG_ON_LINK;
+import static com.android.testutils.MiscAsserts.assertThrows;
import static junit.framework.Assert.fail;
@@ -102,6 +108,7 @@
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkStackIpMemoryStore;
+import android.net.RouteInfo;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
import android.net.Uri;
@@ -111,10 +118,10 @@
import android.net.dhcp.DhcpPacket;
import android.net.dhcp.DhcpPacket.ParseException;
import android.net.dhcp.DhcpRequestPacket;
+import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.Status;
-import android.net.netlink.StructNdOptPref64;
import android.net.networkstack.TestNetworkStackServiceClient;
import android.net.networkstack.aidl.dhcp.DhcpOption;
import android.net.shared.Layer2Information;
@@ -122,6 +129,7 @@
import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.util.InterfaceParams;
import android.net.util.NetworkStackUtils;
+import android.net.util.SharedLog;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -131,22 +139,31 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.stats.connectivity.NetworkQuirkEvent;
import android.system.ErrnoException;
import android.system.Os;
import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.util.HexDump;
import com.android.internal.util.StateMachine;
import com.android.net.module.util.ArrayTrackRecord;
-import com.android.net.module.util.IpUtils;
+import com.android.net.module.util.Ipv6Utils;
+import com.android.net.module.util.netlink.StructNdOptPref64;
+import com.android.net.module.util.structs.LlaOption;
+import com.android.net.module.util.structs.PrefixInformationOption;
+import com.android.net.module.util.structs.RdnssOption;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.common.ShimUtils;
import com.android.networkstack.arp.ArpPacket;
import com.android.networkstack.metrics.IpProvisioningMetrics;
+import com.android.networkstack.metrics.IpReachabilityMonitorMetrics;
+import com.android.networkstack.metrics.NetworkQuirkMetrics;
+import com.android.networkstack.packets.NeighborAdvertisement;
+import com.android.networkstack.packets.NeighborSolicitation;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
@@ -163,6 +180,7 @@
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -180,6 +198,7 @@
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
@@ -205,7 +224,7 @@
*
* Tests in this class can either be run with signature permissions, or with root access.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
@SmallTest
public abstract class IpClientIntegrationTestCommon {
private static final int DATA_BUFFER_LEN = 4096;
@@ -228,6 +247,17 @@
@Rule
public final TestName mTestNameRule = new TestName();
+ // Indicate whether the flag of parsing netlink event is enabled or not. If it's disabled,
+ // integration test still covers the old codepath(i.e. using NetworkObserver), otherwise,
+ // test goes through the new codepath(i.e. processRtNetlinkxxx).
+ @Parameterized.Parameter(0)
+ public boolean mIsNetlinkEventParseEnabled;
+
+ @Parameterized.Parameters
+ public static Iterable<? extends Object> data() {
+ return Arrays.asList(Boolean.valueOf("false"), Boolean.valueOf("true"));
+ }
+
/**
* Indicates that a test requires signature permissions to run.
*
@@ -258,6 +288,9 @@
@Mock private IpMemoryStoreService mIpMemoryStoreService;
@Mock private PowerManager.WakeLock mTimeoutWakeLock;
@Mock protected NetworkStackIpMemoryStore mIpMemoryStore;
+ @Mock private NetworkQuirkMetrics.Dependencies mNetworkQuirkMetricsDeps;
+ @Mock private IpReachabilityMonitorMetrics mIpReachabilityMonitorMetrics;
+ @Mock protected IpReachabilityMonitor.Callback mCallback;
@Spy private INetd mNetd;
private NetworkObserverRegistry mNetworkObserverRegistry;
@@ -267,7 +300,7 @@
/***** END signature required test members *****/
- private IIpClientCallbacks mCb;
+ protected IIpClientCallbacks mCb;
private IIpClient mIIpClient;
private String mIfaceName;
private HandlerThread mPacketReaderThread;
@@ -322,7 +355,10 @@
private static final String HOSTNAME = "testhostname";
private static final int TEST_DEFAULT_MTU = 1500;
private static final int TEST_MIN_MTU = 1280;
- private static final byte[] SERVER_MAC = new byte[] { 0x00, 0x1A, 0x11, 0x22, 0x33, 0x44 };
+ private static final MacAddress ROUTER_MAC = MacAddress.fromString("00:1A:11:22:33:44");
+ private static final byte[] ROUTER_MAC_BYTES = ROUTER_MAC.toByteArray();
+ private static final Inet6Address ROUTER_LINK_LOCAL =
+ (Inet6Address) InetAddresses.parseNumericAddress("fe80::1");
private static final String TEST_HOST_NAME = "AOSP on Crosshatch";
private static final String TEST_HOST_NAME_TRANSLITERATION = "AOSP-on-Crosshatch";
private static final String TEST_CAPTIVE_PORTAL_URL = "https://example.com/capportapi";
@@ -348,32 +384,12 @@
};
protected class Dependencies extends IpClient.Dependencies {
- private boolean mIsDhcpLeaseCacheEnabled;
- private boolean mIsDhcpRapidCommitEnabled;
- private boolean mIsDhcpIpConflictDetectEnabled;
// Can't use SparseIntArray, it doesn't have an easy way to know if a key is not present.
private HashMap<String, Integer> mIntConfigProperties = new HashMap<>();
private DhcpClient mDhcpClient;
private boolean mIsHostnameConfigurationEnabled;
private String mHostname;
private boolean mIsInterfaceRecovered;
- private boolean mIsIPv6OnlyPreferredEnabled;
-
- public void setDhcpLeaseCacheEnabled(final boolean enable) {
- mIsDhcpLeaseCacheEnabled = enable;
- }
-
- public void setDhcpRapidCommitEnabled(final boolean enable) {
- mIsDhcpRapidCommitEnabled = enable;
- }
-
- public void setDhcpIpConflictDetectEnabled(final boolean enable) {
- mIsDhcpIpConflictDetectEnabled = enable;
- }
-
- public void setIPv6OnlyPreferredEnabled(final boolean enable) {
- mIsIPv6OnlyPreferredEnabled = enable;
- }
public void setHostnameConfiguration(final boolean enable, final String hostname) {
mIsHostnameConfigurationEnabled = enable;
@@ -416,25 +432,28 @@
}
@Override
+ public IpReachabilityMonitor getIpReachabilityMonitor(Context context,
+ InterfaceParams ifParams, Handler h, SharedLog log,
+ IpReachabilityMonitor.Callback callback, boolean usingMultinetworkPolicyTracker,
+ IpReachabilityMonitor.Dependencies deps, final INetd netd) {
+ return new IpReachabilityMonitor(context, ifParams, h, log, mCallback,
+ usingMultinetworkPolicyTracker, deps, netd);
+ }
+
+ @Override
+ public boolean isFeatureEnabled(final Context context, final String name,
+ final boolean defaultEnabled) {
+ return IpClientIntegrationTestCommon.this.isFeatureEnabled(name, defaultEnabled);
+ }
+
+ @Override
public DhcpClient.Dependencies getDhcpClientDependencies(
NetworkStackIpMemoryStore ipMemoryStore, IpProvisioningMetrics metrics) {
return new DhcpClient.Dependencies(ipMemoryStore, metrics) {
@Override
public boolean isFeatureEnabled(final Context context, final String name,
final boolean defaultEnabled) {
- switch (name) {
- case NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION:
- return mIsDhcpRapidCommitEnabled;
- case NetworkStackUtils.DHCP_INIT_REBOOT_VERSION:
- return mIsDhcpLeaseCacheEnabled;
- case NetworkStackUtils.DHCP_IP_CONFLICT_DETECT_VERSION:
- return mIsDhcpIpConflictDetectEnabled;
- case NetworkStackUtils.DHCP_IPV6_ONLY_PREFERRED_VERSION:
- return mIsIPv6OnlyPreferredEnabled;
- default:
- fail("Invalid experiment flag: " + name);
- return false;
- }
+ return Dependencies.this.isFeatureEnabled(context, name, defaultEnabled);
}
@Override
@@ -461,6 +480,32 @@
}
@Override
+ public IpReachabilityMonitor.Dependencies getIpReachabilityMonitorDeps(Context context,
+ String name) {
+ return new IpReachabilityMonitor.Dependencies() {
+ public void acquireWakeLock(long durationMs) {
+ // It doesn't matter for the integration test app on whether the wake lock
+ // is acquired or not.
+ return;
+ }
+
+ public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log,
+ NeighborEventConsumer cb) {
+ return new IpNeighborMonitor(h, log, cb);
+ }
+
+ public boolean isFeatureEnabled(final Context context, final String name,
+ boolean defaultEnabled) {
+ return Dependencies.this.isFeatureEnabled(context, name, defaultEnabled);
+ }
+
+ public IpReachabilityMonitorMetrics getIpReachabilityMonitorMetrics() {
+ return mIpReachabilityMonitorMetrics;
+ }
+ };
+ }
+
+ @Override
public int getDeviceConfigPropertyInt(String name, int defaultValue) {
Integer value = mIntConfigProperties.get(name);
if (value == null) {
@@ -472,22 +517,33 @@
public void setDeviceConfigProperty(String name, int value) {
mIntConfigProperties.put(name, value);
}
+
+ @Override
+ public NetworkQuirkMetrics getNetworkQuirkMetrics() {
+ return new NetworkQuirkMetrics(mNetworkQuirkMetricsDeps);
+ }
}
@NonNull
protected abstract IIpClient makeIIpClient(
@NonNull String ifaceName, @NonNull IIpClientCallbacks cb);
- protected abstract void setDhcpFeatures(boolean isDhcpLeaseCacheEnabled,
- boolean isRapidCommitEnabled, boolean isDhcpIpConflictDetectEnabled,
- boolean isIPv6OnlyPreferredEnabled);
+ protected abstract void setFeatureEnabled(String name, boolean enabled);
+
+ protected abstract boolean isFeatureEnabled(String name, boolean defaultEnabled);
protected abstract boolean useNetworkStackSignature();
protected abstract NetworkAttributes getStoredNetworkAttributes(String l2Key, long timeout);
+ protected abstract void storeNetworkAttributes(String l2Key, NetworkAttributes na);
+
protected abstract void assertIpMemoryNeverStoreNetworkAttributes(String l2Key, long timeout);
+ protected abstract void assertNotifyNeighborLost(Inet6Address targetIp);
+
+ protected abstract void assertNeverNotifyNeighborLost();
+
protected final boolean testSkipped() {
// TODO: split out a test suite for root tests, and fail hard instead of skipping the test
// if it is run on devices where TestNetworkStackServiceClient is not supported
@@ -495,10 +551,27 @@
&& (mIsSignatureRequiredTest || !TestNetworkStackServiceClient.isSupported());
}
+ protected void setDhcpFeatures(final boolean isDhcpLeaseCacheEnabled,
+ final boolean isRapidCommitEnabled, final boolean isDhcpIpConflictDetectEnabled,
+ final boolean isIPv6OnlyPreferredEnabled) {
+ setFeatureEnabled(NetworkStackUtils.DHCP_INIT_REBOOT_VERSION, isDhcpLeaseCacheEnabled);
+ setFeatureEnabled(NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION, isRapidCommitEnabled);
+ setFeatureEnabled(NetworkStackUtils.DHCP_IP_CONFLICT_DETECT_VERSION,
+ isDhcpIpConflictDetectEnabled);
+ setFeatureEnabled(NetworkStackUtils.DHCP_IPV6_ONLY_PREFERRED_VERSION,
+ isIPv6OnlyPreferredEnabled);
+ }
+
@Before
public void setUp() throws Exception {
- final Method testMethod = IpClientIntegrationTestCommon.class.getMethod(
- mTestNameRule.getMethodName());
+ // Suffix "[0]" or "[1]" is added to the end of test method name after running with
+ // Parameterized.class, that's intended behavior, to iterate each test method with the
+ // parameterize value. However, Class#getMethod() throws NoSuchMethodException when
+ // searching the target test method name due to this change. Just keep the original test
+ // method name to fix NoSuchMethodException, and find the correct annotation associated
+ // to test method.
+ final String testMethodName = mTestNameRule.getMethodName().split("\\[")[0];
+ final Method testMethod = IpClientIntegrationTestCommon.class.getMethod(testMethodName);
mIsSignatureRequiredTest = testMethod.getAnnotation(SignatureRequiredTest.class) != null;
assumeFalse(testSkipped());
@@ -511,6 +584,12 @@
}
mIIpClient = makeIIpClient(mIfaceName, mCb);
+
+ // Depend on the parameterized value to enable/disable netlink message refactor flag.
+ // Make sure both of the old codepath(rely on the INetdUnsolicitedEventListener aidl)
+ // and new codepath(parse netlink event from kernel) will be executed.
+ setFeatureEnabled(NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION,
+ mIsNetlinkEventParseEnabled /* default value */);
}
protected void setUpMocks() throws Exception {
@@ -523,6 +602,7 @@
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mNetworkStackServiceManager.getIpMemoryStoreService())
.thenReturn(mIpMemoryStoreService);
+ when(mCb.getInterfaceVersion()).thenReturn(VERSION_ADDED_PROVISIONING_ENUM);
mDependencies.setDeviceConfigProperty(IpClient.CONFIG_MIN_RDNSS_LIFETIME, 67);
mDependencies.setDeviceConfigProperty(DhcpClient.DHCP_RESTART_CONFIG_DELAY, 10);
@@ -709,6 +789,22 @@
}
}
+ private NeighborAdvertisement parseNeighborAdvertisementOrNull(final byte[] packet) {
+ try {
+ return NeighborAdvertisement.parse(packet, packet.length);
+ } catch (NeighborAdvertisement.ParseException e) {
+ return null;
+ }
+ }
+
+ private NeighborSolicitation parseNeighborSolicitationOrNull(final byte[] packet) {
+ try {
+ return NeighborSolicitation.parse(packet, packet.length);
+ } catch (NeighborSolicitation.ParseException e) {
+ return null;
+ }
+ }
+
private static ByteBuffer buildDhcpOfferPacket(final DhcpPacket packet,
final Inet4Address clientAddress, final Integer leaseTimeSec, final short mtu,
final String captivePortalUrl, final Integer ipv6OnlyWaitTime) {
@@ -758,7 +854,7 @@
private void sendArpReply(final byte[] clientMac) throws IOException {
final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */,
- SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */,
+ ROUTER_MAC_BYTES /* srcMac */, INADDR_ANY.getAddress() /* target IP */,
clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */,
(short) ARP_REPLY);
mPacketReader.sendResponse(packet);
@@ -766,7 +862,7 @@
private void sendArpProbe() throws IOException {
final ByteBuffer packet = ArpPacket.buildArpPacket(DhcpPacket.ETHER_BROADCAST /* dst */,
- SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */,
+ ROUTER_MAC_BYTES /* srcMac */, CLIENT_ADDR.getAddress() /* target IP */,
new byte[ETHER_ADDR_LEN] /* target HW address */,
INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST);
mPacketReader.sendResponse(packet);
@@ -779,11 +875,14 @@
private void startIpClientProvisioning(final boolean isDhcpLeaseCacheEnabled,
final boolean shouldReplyRapidCommitAck, final boolean isPreconnectionEnabled,
final boolean isDhcpIpConflictDetectEnabled, final boolean isIPv6OnlyPreferredEnabled,
- final String displayName, final ScanResultInfo scanResultInfo) throws Exception {
+ final String displayName, final ScanResultInfo scanResultInfo,
+ final Layer2Information layer2Info) throws Exception {
ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
.withoutIpReachabilityMonitor()
- .withLayer2Information(new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
- MacAddress.fromString(TEST_DEFAULT_BSSID)))
+ .withLayer2Information(layer2Info == null
+ ? new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_DEFAULT_BSSID))
+ : layer2Info)
.withoutIPv6();
if (isPreconnectionEnabled) prov.withPreconnection();
if (displayName != null) prov.withDisplayName(displayName);
@@ -805,7 +904,7 @@
throws Exception {
startIpClientProvisioning(isDhcpLeaseCacheEnabled, isDhcpRapidCommitEnabled,
isPreconnectionEnabled, isDhcpIpConflictDetectEnabled, isIPv6OnlyPreferredEnabled,
- null /* displayName */, null /* ScanResultInfo */);
+ null /* displayName */, null /* ScanResultInfo */, null /* layer2Info */);
}
private void assertIpMemoryStoreNetworkAttributes(final Integer leaseTimeSec,
@@ -860,10 +959,11 @@
final boolean isDhcpIpConflictDetectEnabled,
final boolean isIPv6OnlyPreferredEnabled,
final String captivePortalApiUrl, final String displayName,
- final ScanResultInfo scanResultInfo) throws Exception {
+ final ScanResultInfo scanResultInfo, final Layer2Information layer2Info)
+ throws Exception {
startIpClientProvisioning(isDhcpLeaseCacheEnabled, shouldReplyRapidCommitAck,
false /* isPreconnectionEnabled */, isDhcpIpConflictDetectEnabled,
- isIPv6OnlyPreferredEnabled, displayName, scanResultInfo);
+ isIPv6OnlyPreferredEnabled, displayName, scanResultInfo, layer2Info);
return handleDhcpPackets(isSuccessLease, leaseTimeSec, shouldReplyRapidCommitAck, mtu,
captivePortalApiUrl);
}
@@ -909,7 +1009,8 @@
return performDhcpHandshake(isSuccessLease, leaseTimeSec, isDhcpLeaseCacheEnabled,
isDhcpRapidCommitEnabled, mtu, isDhcpIpConflictDetectEnabled,
false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */);
+ null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */,
+ null /* layer2Info */);
}
private List<DhcpPacket> performDhcpHandshake() throws Exception {
@@ -918,10 +1019,21 @@
TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */);
}
- private DhcpPacket getNextDhcpPacket() throws ParseException {
- byte[] packet = mDhcpPacketReadHead.getValue().poll(PACKET_TIMEOUT_MS, this::isDhcpPacket);
+ private DhcpPacket getNextDhcpPacket(final long timeout) throws Exception {
+ byte[] packet;
+ while ((packet = mDhcpPacketReadHead.getValue()
+ .poll(timeout, this::isDhcpPacket)) != null) {
+ final DhcpPacket dhcpPacket = DhcpPacket.decodeFullPacket(packet, packet.length,
+ ENCAP_L2);
+ if (dhcpPacket != null) return dhcpPacket;
+ }
+ return null;
+ }
+
+ private DhcpPacket getNextDhcpPacket() throws Exception {
+ final DhcpPacket packet = getNextDhcpPacket(PACKET_TIMEOUT_MS);
assertNotNull("No expected DHCP packet received on interface within timeout", packet);
- return DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L2);
+ return packet;
}
private DhcpPacket getReplyFromDhcpLease(final NetworkAttributes na, boolean timeout)
@@ -1127,6 +1239,14 @@
assertEquals(packet.senderIp, CLIENT_ADDR);
}
+ private void assertGratuitousARP(final ArpPacket packet) {
+ assertEquals(packet.opCode, ARP_REPLY);
+ assertEquals(packet.senderIp, CLIENT_ADDR);
+ assertEquals(packet.targetIp, CLIENT_ADDR);
+ assertTrue(Arrays.equals(packet.senderHwAddress.toByteArray(), mClientMac));
+ assertTrue(Arrays.equals(packet.targetHwAddress.toByteArray(), ETHER_BROADCAST));
+ }
+
private void doIpAddressConflictDetectionTest(final boolean causeIpAddressConflict,
final boolean shouldReplyRapidCommitAck, final boolean isDhcpIpConflictDetectEnabled,
final boolean shouldResponseArpReply) throws Exception {
@@ -1431,12 +1551,43 @@
HandlerUtils.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
}
- private boolean isRouterSolicitation(final byte[] packetBytes) {
+ private boolean isIcmpv6PacketOfType(final byte[] packetBytes, int type) {
ByteBuffer packet = ByteBuffer.wrap(packetBytes);
return packet.getShort(ETHER_TYPE_OFFSET) == (short) ETH_P_IPV6
&& packet.get(ETHER_HEADER_LEN + IPV6_PROTOCOL_OFFSET) == (byte) IPPROTO_ICMPV6
- && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN)
- == (byte) ICMPV6_ROUTER_SOLICITATION;
+ && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN) == (byte) type;
+ }
+
+ private boolean isRouterSolicitation(final byte[] packetBytes) {
+ return isIcmpv6PacketOfType(packetBytes, ICMPV6_ROUTER_SOLICITATION);
+ }
+
+ private boolean isNeighborAdvertisement(final byte[] packetBytes) {
+ return isIcmpv6PacketOfType(packetBytes, ICMPV6_NEIGHBOR_ADVERTISEMENT);
+ }
+
+ private boolean isNeighborSolicitation(final byte[] packetBytes) {
+ return isIcmpv6PacketOfType(packetBytes, ICMPV6_NEIGHBOR_SOLICITATION);
+ }
+
+ private NeighborAdvertisement getNextNeighborAdvertisement() throws ParseException {
+ final byte[] packet = mPacketReader.popPacket(PACKET_TIMEOUT_MS,
+ this::isNeighborAdvertisement);
+ if (packet == null) return null;
+
+ final NeighborAdvertisement na = parseNeighborAdvertisementOrNull(packet);
+ assertNotNull("Invalid neighbour advertisement received", na);
+ return na;
+ }
+
+ private NeighborSolicitation getNextNeighborSolicitation() throws ParseException {
+ final byte[] packet = mPacketReader.popPacket(PACKET_TIMEOUT_MS,
+ this::isNeighborSolicitation);
+ if (packet == null) return null;
+
+ final NeighborSolicitation ns = parseNeighborSolicitationOrNull(packet);
+ assertNotNull("Invalid neighbour solicitation received", ns);
+ return ns;
}
private void waitForRouterSolicitation() throws ParseException {
@@ -1468,111 +1619,26 @@
// TODO: move this and the following method to a common location and use them in ApfTest.
private static ByteBuffer buildPioOption(int valid, int preferred, String prefixString)
throws Exception {
- final int optLen = 4;
- IpPrefix prefix = new IpPrefix(prefixString);
- ByteBuffer option = ByteBuffer.allocate(optLen * ICMPV6_ND_OPTION_LENGTH_SCALING_FACTOR);
- option.put((byte) ICMPV6_ND_OPTION_PIO); // Type
- option.put((byte) optLen); // Length in 8-byte units
- option.put((byte) prefix.getPrefixLength()); // Prefix length
- option.put((byte) 0b11000000); // L = 1, A = 1
- option.putInt(valid);
- option.putInt(preferred);
- option.putInt(0); // Reserved
- option.put(prefix.getRawAddress());
- option.flip();
- return option;
+ return PrefixInformationOption.build(new IpPrefix(prefixString),
+ (byte) (PIO_FLAG_ON_LINK | PIO_FLAG_AUTONOMOUS), valid, preferred);
}
private static ByteBuffer buildRdnssOption(int lifetime, String... servers) throws Exception {
- final int optLen = 1 + 2 * servers.length;
- ByteBuffer option = ByteBuffer.allocate(optLen * ICMPV6_ND_OPTION_LENGTH_SCALING_FACTOR);
- option.put((byte) ICMPV6_ND_OPTION_RDNSS); // Type
- option.put((byte) optLen); // Length in 8-byte units
- option.putShort((short) 0); // Reserved
- option.putInt(lifetime); // Lifetime
- for (String server : servers) {
- option.put(InetAddress.getByName(server).getAddress());
- }
- option.flip();
- return option;
+ return RdnssOption.build(lifetime, servers);
}
- // HACK: these functions are here because IpUtils#transportChecksum is private. Even if we made
- // that public, it won't be available on Q devices, and this test needs to run on Q devices.
- // TODO: move the IpUtils code to frameworks/lib/net and link it statically.
- private static int checksumFold(int sum) {
- while (sum > 0xffff) {
- sum = (sum >> 16) + (sum & 0xffff);
- }
- return sum;
- }
-
- private static short checksumAdjust(short checksum, short oldWord, short newWord) {
- checksum = (short) ~checksum;
- int tempSum = checksumFold(uint16(checksum) + uint16(newWord) + 0xffff - uint16(oldWord));
- return (short) ~tempSum;
- }
-
- public static int uint16(short s) {
- return s & 0xffff;
- }
-
- private static short icmpv6Checksum(ByteBuffer buf, int ipOffset, int transportOffset,
- int transportLen) {
- // The ICMPv6 checksum is the same as the TCP checksum, except the pseudo-header uses
- // 58 (ICMPv6) instead of 6 (TCP). Calculate the TCP checksum, and then do an incremental
- // checksum adjustment for the change in the next header byte.
- short checksum = IpUtils.tcpChecksum(buf, ipOffset, transportOffset, transportLen);
- return checksumAdjust(checksum, (short) IPPROTO_TCP, (short) IPPROTO_ICMPV6);
+ private static ByteBuffer buildSllaOption() throws Exception {
+ return LlaOption.build((byte) ICMPV6_ND_OPTION_SLLA, ROUTER_MAC);
}
private static ByteBuffer buildRaPacket(short lifetime, ByteBuffer... options)
throws Exception {
- final MacAddress srcMac = MacAddress.fromString("33:33:00:00:00:01");
- final MacAddress dstMac = MacAddress.fromString("01:02:03:04:05:06");
- final byte[] routerLinkLocal = InetAddresses.parseNumericAddress("fe80::1").getAddress();
- final byte[] allNodes = InetAddresses.parseNumericAddress("ff02::1").getAddress();
-
- final ByteBuffer packet = ByteBuffer.allocate(TEST_DEFAULT_MTU);
- int icmpLen = ICMPV6_RA_HEADER_LEN;
-
- // Ethernet header.
- packet.put(srcMac.toByteArray());
- packet.put(dstMac.toByteArray());
- packet.putShort((short) ETHER_TYPE_IPV6);
-
- // IPv6 header.
- packet.putInt(0x600abcde); // Version, traffic class, flowlabel
- packet.putShort((short) 0); // Length, TBD
- packet.put((byte) IPPROTO_ICMPV6); // Next header
- packet.put((byte) 0xff); // Hop limit
- packet.put(routerLinkLocal); // Source address
- packet.put(allNodes); // Destination address
-
- // Router advertisement.
- packet.put((byte) ICMPV6_ROUTER_ADVERTISEMENT); // ICMP type
- packet.put((byte) 0); // ICMP code
- packet.putShort((short) 0); // Checksum, TBD
- packet.put((byte) 0); // Hop limit, unspecified
- packet.put((byte) 0); // M=0, O=0
- packet.putShort(lifetime); // Router lifetime
- packet.putInt(0); // Reachable time, unspecified
- packet.putInt(100); // Retrans time 100ms.
-
- for (ByteBuffer option : options) {
- packet.put(option);
- option.clear(); // So we can reuse it in a future packet.
- icmpLen += option.capacity();
- }
-
- // Populate length and checksum fields.
- final int transportOffset = ETHER_HEADER_LEN + IPV6_HEADER_LEN;
- final short checksum = icmpv6Checksum(packet, ETHER_HEADER_LEN, transportOffset, icmpLen);
- packet.putShort(ETHER_HEADER_LEN + IPV6_LEN_OFFSET, (short) icmpLen);
- packet.putShort(transportOffset + ICMPV6_CHECKSUM_OFFSET, checksum);
-
- packet.flip();
- return packet;
+ final MacAddress dstMac =
+ NetworkStackUtils.ipv6MulticastToEthernetMulticast(IPV6_ADDR_ALL_ROUTERS_MULTICAST);
+ return Ipv6Utils.buildRaPacket(ROUTER_MAC /* srcMac */, dstMac,
+ ROUTER_LINK_LOCAL /* srcIp */, IPV6_ADDR_ALL_NODES_MULTICAST /* dstIp */,
+ (byte) 0 /* M=0, O=0 */, lifetime, 0 /* Reachable time, unspecified */,
+ 100 /* Retrans time 100ms */, options);
}
private static ByteBuffer buildRaPacket(ByteBuffer... options) throws Exception {
@@ -1611,6 +1677,17 @@
return addr.isGlobalPreferred() && hasFlag(addr, flag);
}
+ private LinkProperties doIpv6OnlyProvisioning() throws Exception {
+ final InOrder inOrder = inOrder(mCb);
+ final String dnsServer = "2001:4860:4860::64";
+ final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64");
+ final ByteBuffer rdnss = buildRdnssOption(3600, dnsServer);
+ final ByteBuffer slla = buildSllaOption();
+ final ByteBuffer ra = buildRaPacket(pio, rdnss, slla);
+
+ return doIpv6OnlyProvisioning(inOrder, ra);
+ }
+
private LinkProperties doIpv6OnlyProvisioning(InOrder inOrder, ByteBuffer ra) throws Exception {
waitForRouterSolicitation();
mPacketReader.sendResponse(ra);
@@ -2031,6 +2108,52 @@
}
@Test
+ @SignatureRequiredTest(reason = "needs mocked alarm and access to IpClient handler thread")
+ public void testDhcpClientPreconnection_DelayedAbortAndTransitToStoppedState()
+ throws Exception {
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .withPreconnection()
+ .build();
+ setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */,
+ false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
+ startIpClientProvisioning(config);
+ assertDiscoverPacketOnPreconnectionStart();
+
+ // IpClient is in the PreconnectingState, simulate provisioning timeout event
+ // and force IpClient state machine transit to StoppingState.
+ final ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class);
+ final OnAlarmListener alarm = expectAlarmSet(null /* inOrder */, "TIMEOUT", 18,
+ mIpc.getHandler());
+ mIpc.getHandler().post(() -> alarm.onAlarm());
+
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(captor.capture());
+ final LinkProperties lp = captor.getValue();
+ assertNotNull(lp);
+ assertEquals(mIfaceName, lp.getInterfaceName());
+ assertEquals(0, lp.getLinkAddresses().size());
+ assertEquals(0, lp.getRoutes().size());
+ assertEquals(0, lp.getMtu());
+ assertEquals(0, lp.getDnsServers().size());
+
+ // Send preconnection abort message, but IpClient should ignore it at this moment and
+ // transit to StoppedState finally.
+ mIpc.notifyPreconnectionComplete(false /* abort */);
+ mIpc.stop();
+ HandlerUtils.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
+
+ reset(mCb);
+
+ // Start provisioning again to verify IpClient can process CMD_START correctly at
+ // StoppedState.
+ startIpClientProvisioning(false /* isDhcpLeaseCacheEnabled */,
+ false /* shouldReplyRapidCommitAck */, false /* isPreConnectionEnabled */,
+ false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
+ final DhcpPacket discover = getNextDhcpPacket();
+ assertTrue(discover instanceof DhcpDiscoverPacket);
+ }
+
+ @Test
public void testDhcpDecline_conflictByArpReply() throws Exception {
doIpAddressConflictDetectionTest(true /* causeIpAddressConflict */,
false /* shouldReplyRapidCommitAck */, true /* isDhcpIpConflictDetectEnabled */,
@@ -2095,9 +2218,8 @@
final List<DhcpPacket> sentPackets = performDhcpHandshake(true /* isSuccessLease */,
TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */,
false /* isDhcpRapidCommitEnabled */, TEST_DEFAULT_MTU,
- false /* isDhcpIpConflictDetectEnabled */,
- false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */);
+ false /* isDhcpIpConflictDetectEnabled */);
+
assertEquals(2, sentPackets.size());
verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
assertHostname(true, TEST_HOST_NAME, TEST_HOST_NAME_TRANSLITERATION, sentPackets);
@@ -2113,9 +2235,8 @@
final List<DhcpPacket> sentPackets = performDhcpHandshake(true /* isSuccessLease */,
TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */,
false /* isDhcpRapidCommitEnabled */, TEST_DEFAULT_MTU,
- false /* isDhcpIpConflictDetectEnabled */,
- false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */);
+ false /* isDhcpIpConflictDetectEnabled */);
+
assertEquals(2, sentPackets.size());
verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
assertHostname(false, TEST_HOST_NAME, TEST_HOST_NAME_TRANSLITERATION, sentPackets);
@@ -2131,9 +2252,8 @@
final List<DhcpPacket> sentPackets = performDhcpHandshake(true /* isSuccessLease */,
TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */,
false /* isDhcpRapidCommitEnabled */, TEST_DEFAULT_MTU,
- false /* isDhcpIpConflictDetectEnabled */,
- false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */);
+ false /* isDhcpIpConflictDetectEnabled */);
+
assertEquals(2, sentPackets.size());
verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
assertHostname(true, null /* hostname */, null /* hostnameAfterTransliteration */,
@@ -2230,7 +2350,8 @@
false /* isDhcpRapidCommitEnabled */, TEST_DEFAULT_MTU,
false /* isDhcpIpConflictDetectEnabled */,
false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, displayName, info /* scanResultInfo */);
+ null /* captivePortalApiUrl */, displayName, info /* scanResultInfo */,
+ null /* layer2Info */);
assertEquals(2, sentPackets.size());
verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
@@ -2308,11 +2429,18 @@
true /* expectMetered */);
}
+ private void forceLayer2Roaming() throws Exception {
+ final Layer2InformationParcelable roamingInfo = new Layer2InformationParcelable();
+ roamingInfo.bssid = MacAddress.fromString(TEST_DHCP_ROAM_BSSID);
+ roamingInfo.l2Key = TEST_DHCP_ROAM_L2KEY;
+ roamingInfo.cluster = TEST_DHCP_ROAM_CLUSTER;
+ mIIpClient.updateLayer2Information(roamingInfo);
+ }
+
private void doDhcpRoamingTest(final boolean hasMismatchedIpAddress, final String displayName,
- final String ssid, final String bssid, final boolean expectRoaming) throws Exception {
+ final MacAddress bssid, final boolean expectRoaming) throws Exception {
long currentTime = System.currentTimeMillis();
- final ScanResultInfo scanResultInfo = (ssid == null || bssid == null)
- ? null : makeScanResultInfo(ssid, bssid);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, bssid);
doAnswer(invocation -> {
// we don't rely on the Init-Reboot state to renew previous cached IP lease.
@@ -2329,16 +2457,13 @@
true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */,
false /* isIPv6OnlyPreferredEnabled */,
- null /* captivePortalApiUrl */, displayName, scanResultInfo);
+ null /* captivePortalApiUrl */, displayName, null /* scanResultInfo */,
+ layer2Info);
verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU);
// simulate the roaming by updating bssid.
- final Layer2InformationParcelable roamingInfo = new Layer2InformationParcelable();
- roamingInfo.bssid = MacAddress.fromString(TEST_DHCP_ROAM_BSSID);
- roamingInfo.l2Key = TEST_DHCP_ROAM_L2KEY;
- roamingInfo.cluster = TEST_DHCP_ROAM_CLUSTER;
- mIpc.updateLayer2Information(roamingInfo);
+ forceLayer2Roaming();
currentTime = System.currentTimeMillis();
reset(mIpMemoryStore);
@@ -2379,57 +2504,41 @@
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
public void testDhcpRoaming() throws Exception {
doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
- TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, true /* expectRoaming */);
+ MacAddress.fromString(TEST_DEFAULT_BSSID), true /* expectRoaming */);
}
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
public void testDhcpRoaming_invalidBssid() throws Exception {
doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
- TEST_DHCP_ROAM_SSID, TEST_DHCP_ROAM_BSSID, false /* expectRoaming */);
+ MacAddress.fromString(TEST_DHCP_ROAM_BSSID), false /* expectRoaming */);
}
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
- public void testDhcpRoaming_nullScanResultInfo() throws Exception {
+ public void testDhcpRoaming_nullBssid() throws Exception {
doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
- null /* SSID */, null /* BSSID */, false /* expectRoaming */);
- }
-
- @Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
- public void testDhcpRoaming_invalidSsid() throws Exception {
- doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
- TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID, false /* expectRoaming */);
+ null /* BSSID */, false /* expectRoaming */);
}
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
public void testDhcpRoaming_invalidDisplayName() throws Exception {
doDhcpRoamingTest(false /* hasMismatchedIpAddress */, "\"test-ssid\"" /* display name */,
- TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, false /* expectRoaming */);
+ MacAddress.fromString(TEST_DEFAULT_BSSID), false /* expectRoaming */);
}
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
public void testDhcpRoaming_mismatchedLeasedIpAddress() throws Exception {
doDhcpRoamingTest(true /* hasMismatchedIpAddress */, "\"0001docomo\"" /* display name */,
- TEST_DHCP_ROAM_SSID, TEST_DEFAULT_BSSID, true /* expectRoaming */);
+ MacAddress.fromString(TEST_DEFAULT_BSSID), true /* expectRoaming */);
}
- private void doDualStackProvisioning() throws Exception {
- when(mCm.shouldAvoidBadWifi()).thenReturn(true);
-
- final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
- .withoutIpReachabilityMonitor()
- .build();
- // Enable rapid commit to accelerate DHCP handshake to shorten test duration,
- // not strictly necessary.
- setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, true /* isRapidCommitEnabled */,
- false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
- mIpc.startProvisioning(config);
-
+ private void performDualStackProvisioning() throws Exception {
final InOrder inOrder = inOrder(mCb);
final CompletableFuture<LinkProperties> lpFuture = new CompletableFuture<>();
final String dnsServer = "2001:4860:4860::64";
final ByteBuffer pio = buildPioOption(3600, 1800, "2001:db8:1::/64");
final ByteBuffer rdnss = buildRdnssOption(3600, dnsServer);
- final ByteBuffer ra = buildRaPacket(pio, rdnss);
+ final ByteBuffer slla = buildSllaOption();
+ final ByteBuffer ra = buildRaPacket(pio, rdnss, slla);
doIpv6OnlyProvisioning(inOrder, ra);
@@ -2450,9 +2559,27 @@
reset(mCb);
}
- @Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
- public void testIgnoreIpv6ProvisioningLoss() throws Exception {
- doDualStackProvisioning();
+ private void doDualStackProvisioning(boolean shouldDisableAcceptRa) throws Exception {
+ when(mCm.shouldAvoidBadWifi()).thenReturn(true);
+
+ final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .build();
+
+ setFeatureEnabled(NetworkStackUtils.IPCLIENT_DISABLE_ACCEPT_RA_VERSION,
+ shouldDisableAcceptRa);
+ // Enable rapid commit to accelerate DHCP handshake to shorten test duration,
+ // not strictly necessary.
+ setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, true /* isRapidCommitEnabled */,
+ false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
+ mIpc.startProvisioning(config);
+
+ performDualStackProvisioning();
+ }
+
+ @Test @SignatureRequiredTest(reason = "signature perms are required due to mocked callabck")
+ public void testIgnoreIpv6ProvisioningLoss_disableIPv6Stack() throws Exception {
+ doDualStackProvisioning(false /* shouldDisableAcceptRa */);
final CompletableFuture<LinkProperties> lpFuture = new CompletableFuture<>();
@@ -2474,11 +2601,52 @@
assertNotNull(lp);
assertEquals(lp.getAddresses().get(0), CLIENT_ADDR);
assertEquals(lp.getDnsServers().get(0), SERVER_ADDR);
+
+ final ArgumentCaptor<Integer> quirkEvent = ArgumentCaptor.forClass(Integer.class);
+ verify(mNetworkQuirkMetricsDeps, timeout(TEST_TIMEOUT_MS)).writeStats(quirkEvent.capture());
+ assertEquals((long) quirkEvent.getValue(),
+ (long) NetworkQuirkEvent.QE_IPV6_PROVISIONING_ROUTER_LOST.ordinal());
+ }
+
+ @Test @SignatureRequiredTest(reason = "signature perms are required due to mocked callabck")
+ public void testIgnoreIpv6ProvisioningLoss_disableAcceptRa() throws Exception {
+ doDualStackProvisioning(true /* shouldDisableAcceptRa */);
+
+ final CompletableFuture<LinkProperties> lpFuture = new CompletableFuture<>();
+
+ // Send RA with 0-lifetime and wait until all global IPv6 addresses, IPv6-related default
+ // route and DNS servers have been removed, then verify if there is IPv4-only, IPv6 link
+ // local address and route to fe80::/64 info left in the LinkProperties.
+ sendRouterAdvertisementWithZeroLifetime();
+ verify(mCb, timeout(TEST_TIMEOUT_MS).atLeastOnce()).onLinkPropertiesChange(
+ argThat(x -> {
+ // Only IPv4 provisioned and IPv6 link-local address
+ final boolean isIPv6LinkLocalAndIPv4OnlyProvisioned =
+ (x.getLinkAddresses().size() == 2
+ && x.getDnsServers().size() == 1
+ && x.getAddresses().get(0) instanceof Inet4Address
+ && x.getDnsServers().get(0) instanceof Inet4Address);
+
+ if (!isIPv6LinkLocalAndIPv4OnlyProvisioned) return false;
+ lpFuture.complete(x);
+ return true;
+ }));
+ final LinkProperties lp = lpFuture.get(TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assertNotNull(lp);
+ assertEquals(lp.getAddresses().get(0), CLIENT_ADDR);
+ assertEquals(lp.getDnsServers().get(0), SERVER_ADDR);
+ assertTrue(lp.getAddresses().get(1).isLinkLocalAddress());
+
+ reset(mCb);
+
+ // Send an RA to verify that global IPv6 addresses won't be configured on the interface.
+ sendBasicRouterAdvertisement(false /* waitForRs */);
+ verify(mCb, timeout(TEST_TIMEOUT_MS).times(0)).onLinkPropertiesChange(any());
}
@Test @SignatureRequiredTest(reason = "TODO: evaluate whether signature perms are required")
public void testDualStackProvisioning() throws Exception {
- doDualStackProvisioning();
+ doDualStackProvisioning(false /* shouldDisableAcceptRa */);
verify(mCb, never()).onProvisioningFailure(any());
}
@@ -2594,20 +2762,20 @@
verifyDhcpPacketRequestsIPv6OnlyPreferredOption(DhcpRequestPacket.class);
}
+ private void setUpRetrievedNetworkAttributesForInitRebootState() {
+ final NetworkAttributes na = new NetworkAttributes.Builder()
+ .setAssignedV4Address(CLIENT_ADDR)
+ .setAssignedV4AddressExpiry(Long.MAX_VALUE) // lease is always valid
+ .setMtu(new Integer(TEST_DEFAULT_MTU))
+ .setCluster(TEST_CLUSTER)
+ .setDnsAddresses(Collections.singletonList(SERVER_ADDR))
+ .build();
+ storeNetworkAttributes(TEST_L2KEY, na);
+ }
+
private void startFromInitRebootStateWithIPv6OnlyPreferredOption(final Integer ipv6OnlyWaitTime,
final long expectedWaitSecs) throws Exception {
- doAnswer(invocation -> {
- ((OnNetworkAttributesRetrievedListener) invocation.getArgument(1))
- .onNetworkAttributesRetrieved(new Status(SUCCESS), TEST_L2KEY,
- new NetworkAttributes.Builder()
- .setAssignedV4Address(CLIENT_ADDR)
- .setAssignedV4AddressExpiry(Long.MAX_VALUE) // lease is always valid
- .setMtu(new Integer(TEST_DEFAULT_MTU))
- .setCluster(TEST_CLUSTER)
- .setDnsAddresses(Collections.singletonList(SERVER_ADDR))
- .build());
- return null;
- }).when(mIpMemoryStore).retrieveNetworkAttributes(eq(TEST_L2KEY), any());
+ setUpRetrievedNetworkAttributesForInitRebootState();
final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
.withoutIpReachabilityMonitor()
@@ -2698,7 +2866,7 @@
public void testNoFdLeaks() throws Exception {
// Shut down and restart IpClient once to ensure that any fds that are opened the first
// time it runs do not cause the test to fail.
- doDualStackProvisioning();
+ doDualStackProvisioning(false /* shouldDisableAcceptRa */);
shutdownAndRecreateIpClient();
// Unfortunately we cannot use a large number of iterations as it would make the test run
@@ -2706,7 +2874,7 @@
final int iterations = 10;
final int before = getNumOpenFds();
for (int i = 0; i < iterations; i++) {
- doDualStackProvisioning();
+ doDualStackProvisioning(false /* shouldDisableAcceptRa */);
shutdownAndRecreateIpClient();
// The last time this loop runs, mIpc will be shut down in tearDown.
}
@@ -2734,7 +2902,7 @@
);
private DhcpPacket doCustomizedDhcpOptionsTest(final List<DhcpOption> options,
- final ScanResultInfo info) throws Exception {
+ final ScanResultInfo info, boolean isDhcpLeaseCacheEnabled) throws Exception {
ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
.withoutIpReachabilityMonitor()
.withLayer2Information(new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
@@ -2743,7 +2911,7 @@
.withDhcpOptions(options)
.withoutIPv6();
- setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, false /* isRapidCommitEnabled */,
+ setDhcpFeatures(isDhcpLeaseCacheEnabled, false /* isRapidCommitEnabled */,
false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
startIpClientProvisioning(prov.build());
@@ -2754,10 +2922,11 @@
}
@Test
- public void testCustomizedDhcpOptions() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions() throws Exception {
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
@@ -2765,10 +2934,11 @@
}
@Test
- public void testCustomizedDhcpOptions_nullDhcpOptions() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_nullDhcpOptions() throws Exception {
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(null /* options */, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(null /* options */, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2776,9 +2946,9 @@
}
@Test
- public void testCustomizedDhcpOptions_nullScanResultInfo() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_nullScanResultInfo() throws Exception {
final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS,
- null /* scanResultInfo */);
+ null /* scanResultInfo */, false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2786,10 +2956,11 @@
}
@Test
- public void testCustomizedDhcpOptions_disallowedOui() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_disallowedOui() throws Exception {
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */,
new byte[]{ 0x00, 0x11, 0x22} /* oui */, (byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2797,10 +2968,11 @@
}
@Test
- public void testCustomizedDhcpOptions_invalidIeId() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_invalidIeId() throws Exception {
final ScanResultInfo info = makeScanResultInfo(0xde /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2808,10 +2980,11 @@
}
@Test
- public void testCustomizedDhcpOptions_invalidVendorSpecificType() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_invalidVendorSpecificType() throws Exception {
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x10 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2819,24 +2992,25 @@
}
@Test
- public void testCustomizedDhcpOptions_disallowedOption() throws Exception {
+ public void testDisoverCustomizedDhcpOptions_disallowedOption() throws Exception {
final List<DhcpOption> options = Arrays.asList(
makeDhcpOption((byte) 60, TEST_OEM_VENDOR_ID.getBytes()),
makeDhcpOption((byte) 77, TEST_OEM_USER_CLASS_INFO),
- // DHCP_HOST_NAME
- makeDhcpOption((byte) 12, new String("Pixel 3 XL").getBytes()));
+ // Option 26: MTU
+ makeDhcpOption((byte) 26, HexDump.toByteArray(TEST_DEFAULT_MTU)));
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
assertArrayEquals(packet.mUserClass, TEST_OEM_USER_CLASS_INFO);
- assertNull(packet.mHostName);
+ assertNull(packet.mMtu);
}
@Test
- public void testCustomizedDhcpOptions_disallowedParamRequestOption() throws Exception {
+ public void testDiscoverCustomizedDhcpOptions_disallowedParamRequestOption() throws Exception {
final List<DhcpOption> options = Arrays.asList(
makeDhcpOption((byte) 60, TEST_OEM_VENDOR_ID.getBytes()),
makeDhcpOption((byte) 77, TEST_OEM_USER_CLASS_INFO),
@@ -2844,11 +3018,512 @@
makeDhcpOption((byte) 42, null));
final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
(byte) 0x17 /* vendor-specific IE type */);
- final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ false /* isDhcpLeaseCacheEnabled */);
assertTrue(packet instanceof DhcpDiscoverPacket);
assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
assertArrayEquals(packet.mUserClass, TEST_OEM_USER_CLASS_INFO);
assertFalse(packet.hasRequestedParam((byte) 42 /* NTP_SERVER */));
}
+
+ @Test
+ public void testDiscoverCustomizedDhcpOptions_ParameterRequestListOnly() throws Exception {
+ final List<DhcpOption> options = Arrays.asList(
+ // DHCP_USER_CLASS
+ makeDhcpOption((byte) 77, null));
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ false /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpDiscoverPacket);
+ assertTrue(packet.hasRequestedParam((byte) 77 /* DHCP_USER_CLASS */));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
+ assertArrayEquals(packet.mUserClass, TEST_OEM_USER_CLASS_INFO);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_nullDhcpOptions() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(null /* options */, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_nullScanResultInfo() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS,
+ null /* scanResultInfo */, true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_disallowedOui() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */,
+ new byte[]{ 0x00, 0x11, 0x22} /* oui */, (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_invalidIeId() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final ScanResultInfo info = makeScanResultInfo(0xde /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_invalidVendorSpecificType() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x10 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
+ assertNull(packet.mUserClass);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_disallowedOption() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final List<DhcpOption> options = Arrays.asList(
+ makeDhcpOption((byte) 60, TEST_OEM_VENDOR_ID.getBytes()),
+ makeDhcpOption((byte) 77, TEST_OEM_USER_CLASS_INFO),
+ // Option 26: MTU
+ makeDhcpOption((byte) 26, HexDump.toByteArray(TEST_DEFAULT_MTU)));
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
+ assertArrayEquals(packet.mUserClass, TEST_OEM_USER_CLASS_INFO);
+ assertNull(packet.mMtu);
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_disallowedParamRequestOption() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final List<DhcpOption> options = Arrays.asList(
+ makeDhcpOption((byte) 60, TEST_OEM_VENDOR_ID.getBytes()),
+ makeDhcpOption((byte) 77, TEST_OEM_USER_CLASS_INFO),
+ // NTP_SERVER
+ makeDhcpOption((byte) 42, null));
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
+ assertArrayEquals(packet.mUserClass, TEST_OEM_USER_CLASS_INFO);
+ assertFalse(packet.hasRequestedParam((byte) 42 /* NTP_SERVER */));
+ }
+
+ @Test
+ public void testRequestCustomizedDhcpOptions_ParameterRequestListOnly() throws Exception {
+ setUpRetrievedNetworkAttributesForInitRebootState();
+
+ final List<DhcpOption> options = Arrays.asList(
+ // DHCP_USER_CLASS
+ makeDhcpOption((byte) 77, null));
+ final ScanResultInfo info = makeScanResultInfo(0xdd /* vendor-specificIE */, TEST_OEM_OUI,
+ (byte) 0x17 /* vendor-specific IE type */);
+ final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info,
+ true /* isDhcpLeaseCacheEnabled */);
+
+ assertTrue(packet instanceof DhcpRequestPacket);
+ assertTrue(packet.hasRequestedParam((byte) 77 /* DHCP_USER_CLASS */));
+ assertNull(packet.mUserClass);
+ }
+
+ private void assertGratuitousNa(final NeighborAdvertisement na) throws Exception {
+ final MacAddress etherMulticast =
+ NetworkStackUtils.ipv6MulticastToEthernetMulticast(IPV6_ADDR_ALL_ROUTERS_MULTICAST);
+ final LinkAddress target = new LinkAddress(na.naHdr.target, 64);
+
+ assertEquals(etherMulticast, na.ethHdr.dstMac);
+ assertEquals(ETH_P_IPV6, na.ethHdr.etherType);
+ assertEquals(IPPROTO_ICMPV6, na.ipv6Hdr.nextHeader);
+ assertEquals(0xff, na.ipv6Hdr.hopLimit);
+ assertTrue(na.ipv6Hdr.srcIp.isLinkLocalAddress());
+ assertEquals(IPV6_ADDR_ALL_ROUTERS_MULTICAST, na.ipv6Hdr.dstIp);
+ assertEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, na.icmpv6Hdr.type);
+ assertEquals(0, na.icmpv6Hdr.code);
+ assertEquals(0, na.naHdr.flags);
+ assertTrue(target.isGlobalPreferred());
+ }
+
+ @Test
+ public void testGratuitousNaForNewGlobalUnicastAddresses() throws Exception {
+ final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .withoutIPv4()
+ .build();
+
+ setFeatureEnabled(NetworkStackUtils.IPCLIENT_GRATUITOUS_NA_VERSION,
+ true /* isGratuitousNaEnabled */);
+ assertTrue(isFeatureEnabled(NetworkStackUtils.IPCLIENT_GRATUITOUS_NA_VERSION, false));
+ startIpClientProvisioning(config);
+
+ doIpv6OnlyProvisioning();
+
+ final List<NeighborAdvertisement> naList = new ArrayList<>();
+ NeighborAdvertisement packet;
+ while ((packet = getNextNeighborAdvertisement()) != null) {
+ assertGratuitousNa(packet);
+ naList.add(packet);
+ }
+ assertEquals(2, naList.size()); // privacy address and stable privacy address
+ }
+
+ private void startGratuitousArpAndNaAfterRoamingTest(boolean isGratuitousArpNaRoamingEnabled,
+ boolean hasIpv4, boolean hasIpv6) throws Exception {
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_DEFAULT_BSSID));
+ final ScanResultInfo scanResultInfo =
+ makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID);
+ final ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .withLayer2Information(layer2Info)
+ .withScanResultInfo(scanResultInfo)
+ .withDisplayName("ssid");
+ if (!hasIpv4) prov.withoutIPv4();
+ if (!hasIpv6) prov.withoutIPv6();
+
+ // Enable rapid commit to accelerate DHCP handshake to shorten test duration,
+ // not strictly necessary.
+ setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, true /* isRapidCommitEnabled */,
+ false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
+ if (isGratuitousArpNaRoamingEnabled) {
+ setFeatureEnabled(NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION, true);
+ assertTrue(isFeatureEnabled(NetworkStackUtils.IPCLIENT_GARP_NA_ROAMING_VERSION, false));
+ }
+ startIpClientProvisioning(prov.build());
+ }
+
+ private void waitForGratuitousArpAndNaPacket(final List<ArpPacket> arpList,
+ final List<NeighborAdvertisement> naList) throws Exception {
+ NeighborAdvertisement na;
+ ArpPacket garp;
+ do {
+ na = getNextNeighborAdvertisement();
+ if (na != null) {
+ assertGratuitousNa(na);
+ naList.add(na);
+ }
+ garp = getNextArpPacket(TEST_TIMEOUT_MS);
+ if (garp != null) {
+ assertGratuitousARP(garp);
+ arpList.add(garp);
+ }
+ } while (na != null || garp != null);
+ }
+
+ @Test
+ public void testGratuitousArpAndNaAfterRoaming() throws Exception {
+ startGratuitousArpAndNaAfterRoamingTest(true /* isGratuitousArpNaRoamingEnabled */,
+ true /* hasIpv4 */, true /* hasIpv6 */);
+ performDualStackProvisioning();
+ forceLayer2Roaming();
+
+ final List<ArpPacket> arpList = new ArrayList<>();
+ final List<NeighborAdvertisement> naList = new ArrayList<>();
+ waitForGratuitousArpAndNaPacket(arpList, naList);
+ assertEquals(2, naList.size()); // privacy address and stable privacy address
+ assertEquals(1, arpList.size()); // IPv4 address
+ }
+
+ @Test
+ public void testGratuitousArpAndNaAfterRoaming_disableExpFlag() throws Exception {
+ startGratuitousArpAndNaAfterRoamingTest(false /* isGratuitousArpNaRoamingEnabled */,
+ true /* hasIpv4 */, true /* hasIpv6 */);
+ performDualStackProvisioning();
+ forceLayer2Roaming();
+
+ final List<ArpPacket> arpList = new ArrayList<>();
+ final List<NeighborAdvertisement> naList = new ArrayList<>();
+ waitForGratuitousArpAndNaPacket(arpList, naList);
+ assertEquals(0, naList.size());
+ assertEquals(0, arpList.size());
+ }
+
+ @Test
+ public void testGratuitousArpAndNaAfterRoaming_IPv6OnlyNetwork() throws Exception {
+ startGratuitousArpAndNaAfterRoamingTest(true /* isGratuitousArpNaRoamingEnabled */,
+ false /* hasIpv4 */, true /* hasIpv6 */);
+ doIpv6OnlyProvisioning();
+ forceLayer2Roaming();
+
+ final List<ArpPacket> arpList = new ArrayList<>();
+ final List<NeighborAdvertisement> naList = new ArrayList<>();
+ waitForGratuitousArpAndNaPacket(arpList, naList);
+ assertEquals(2, naList.size());
+ assertEquals(0, arpList.size());
+ }
+
+ @Test
+ public void testGratuitousArpAndNaAfterRoaming_IPv4OnlyNetwork() throws Exception {
+ startGratuitousArpAndNaAfterRoamingTest(true /* isGratuitousArpNaRoamingEnabled */,
+ true /* hasIpv4 */, false /* hasIpv6 */);
+
+ // Start IPv4 provisioning and wait until entire provisioning completes.
+ handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
+ true /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, null /* serverSentUrl */);
+ verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
+ forceLayer2Roaming();
+
+ final List<ArpPacket> arpList = new ArrayList<>();
+ final List<NeighborAdvertisement> naList = new ArrayList<>();
+ waitForGratuitousArpAndNaPacket(arpList, naList);
+ assertEquals(0, naList.size());
+ assertEquals(1, arpList.size());
+ }
+
+ private void assertNeighborSolicitation(final NeighborSolicitation ns,
+ final Inet6Address target) {
+ assertEquals(ETH_P_IPV6, ns.ethHdr.etherType);
+ assertEquals(IPPROTO_ICMPV6, ns.ipv6Hdr.nextHeader);
+ assertEquals(0xff, ns.ipv6Hdr.hopLimit);
+ assertTrue(ns.ipv6Hdr.srcIp.isLinkLocalAddress());
+ assertEquals(ICMPV6_NEIGHBOR_SOLICITATION, ns.icmpv6Hdr.type);
+ assertEquals(0, ns.icmpv6Hdr.code);
+ assertEquals(0, ns.nsHdr.reserved);
+ assertEquals(target, ns.nsHdr.target);
+ assertEquals(ns.slla.linkLayerAddress, ns.ethHdr.srcMac);
+ }
+
+ private void assertUnicastNeighborSolicitation(final NeighborSolicitation ns,
+ final MacAddress dstMac, final Inet6Address dstIp, final Inet6Address target) {
+ assertEquals(dstMac, ns.ethHdr.dstMac);
+ assertEquals(dstIp, ns.ipv6Hdr.dstIp);
+ assertNeighborSolicitation(ns, target);
+ }
+
+ private void assertMulticastNeighborSolicitation(final NeighborSolicitation ns,
+ final Inet6Address target) {
+ final MacAddress etherMulticast =
+ NetworkStackUtils.ipv6MulticastToEthernetMulticast(ns.ipv6Hdr.dstIp);
+ assertEquals(etherMulticast, ns.ethHdr.dstMac);
+ assertTrue(ns.ipv6Hdr.dstIp.isMulticastAddress());
+ assertNeighborSolicitation(ns, target);
+ }
+
+ private NeighborSolicitation waitForUnicastNeighborSolicitation(final MacAddress dstMac,
+ final Inet6Address dstIp, final Inet6Address targetIp) throws Exception {
+ NeighborSolicitation ns;
+ while ((ns = getNextNeighborSolicitation()) != null) {
+ // Filter out the NSes used for duplicate address detetction, the target address
+ // is the global IPv6 address inside these NSes.
+ if (ns.nsHdr.target.isLinkLocalAddress()) break;
+ }
+ assertNotNull("No unicast Neighbor solicitation received on interface within timeout", ns);
+ assertUnicastNeighborSolicitation(ns, dstMac, dstIp, targetIp);
+ return ns;
+ }
+
+ private List<NeighborSolicitation> waitForMultipleNeighborSolicitations() throws Exception {
+ NeighborSolicitation ns;
+ final List<NeighborSolicitation> nsList = new ArrayList<NeighborSolicitation>();
+ while ((ns = getNextNeighborSolicitation()) != null) {
+ // Filter out the NSes used for duplicate address detetction, the target address
+ // is the global IPv6 address inside these NSes.
+ if (ns.nsHdr.target.isLinkLocalAddress()) {
+ nsList.add(ns);
+ }
+ }
+ assertFalse(nsList.isEmpty());
+ return nsList;
+ }
+
+ // Override this function with disabled experiment flag by default, in order not to
+ // affect those tests which are just related to basic IpReachabilityMonitor infra.
+ private void prepareIpReachabilityMonitorTest() throws Exception {
+ prepareIpReachabilityMonitorTest(false /* isMulticastResolicitEnabled */);
+ }
+
+ private void prepareIpReachabilityMonitorTest(boolean isMulticastResolicitEnabled)
+ throws Exception {
+ final ScanResultInfo info = makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID);
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withLayer2Information(new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_DEFAULT_BSSID)))
+ .withScanResultInfo(info)
+ .withDisplayName(TEST_DEFAULT_SSID)
+ .withoutIPv4()
+ .build();
+ setFeatureEnabled(NetworkStackUtils.IP_REACHABILITY_MCAST_RESOLICIT_VERSION,
+ isMulticastResolicitEnabled);
+ startIpClientProvisioning(config);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+ doIpv6OnlyProvisioning();
+
+ // Simulate the roaming.
+ forceLayer2Roaming();
+ }
+
+ @Test
+ public void testIpReachabilityMonitor_probeFailed() throws Exception {
+ prepareIpReachabilityMonitorTest();
+
+ final List<NeighborSolicitation> nsList = waitForMultipleNeighborSolicitations();
+ assertEquals(MIN_NUD_SOLICIT_NUM, nsList.size());
+ for (NeighborSolicitation ns : nsList) {
+ assertUnicastNeighborSolicitation(ns, ROUTER_MAC /* dstMac */,
+ ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+ }
+ assertNotifyNeighborLost(ROUTER_LINK_LOCAL /* targetIp */);
+ }
+
+ @Test
+ public void testIpReachabilityMonitor_probeReachable() throws Exception {
+ prepareIpReachabilityMonitorTest();
+
+ final NeighborSolicitation ns = waitForUnicastNeighborSolicitation(ROUTER_MAC /* dstMac */,
+ ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+
+ // Reply Neighbor Advertisement and check notifyLost callback won't be triggered.
+ int flag = NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER | NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED;
+ final ByteBuffer na = NeighborAdvertisement.build(ROUTER_MAC /* srcMac */,
+ ns.ethHdr.srcMac /* dstMac */, ROUTER_LINK_LOCAL /* srcIp */,
+ ns.ipv6Hdr.srcIp /* dstIp */, flag, ROUTER_LINK_LOCAL /* target */);
+ mPacketReader.sendResponse(na);
+ assertNeverNotifyNeighborLost();
+ }
+
+ @Test
+ public void testIpReachabilityMonitor_mcastResoclicitProbeFailed() throws Exception {
+ prepareIpReachabilityMonitorTest(true /* isMulticastResolicitEnabled */);
+
+ final List<NeighborSolicitation> nsList = waitForMultipleNeighborSolicitations();
+ int expectedSize = MIN_NUD_SOLICIT_NUM + NUD_MCAST_RESOLICIT_NUM;
+ assertEquals(expectedSize, nsList.size()); // 5 unicast NSes + 3 multicast NSes
+ for (NeighborSolicitation ns : nsList.subList(0, MIN_NUD_SOLICIT_NUM)) {
+ assertUnicastNeighborSolicitation(ns, ROUTER_MAC /* dstMac */,
+ ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+ }
+ for (NeighborSolicitation ns : nsList.subList(MIN_NUD_SOLICIT_NUM, nsList.size())) {
+ assertMulticastNeighborSolicitation(ns, ROUTER_LINK_LOCAL /* targetIp */);
+ }
+ assertNotifyNeighborLost(ROUTER_LINK_LOCAL /* targetIp */);
+ }
+
+ @Test
+ public void testIpReachabilityMonitor_mcastResoclicitProbeReachableWithSameLinkLayerAddress()
+ throws Exception {
+ prepareIpReachabilityMonitorTest(true /* isMulticastResolicitEnabled */);
+
+ final NeighborSolicitation ns = waitForUnicastNeighborSolicitation(ROUTER_MAC /* dstMac */,
+ ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+
+ // Reply Neighbor Advertisement and check notifyLost callback won't be triggered.
+ int flag = NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER | NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED;
+ final ByteBuffer na = NeighborAdvertisement.build(ROUTER_MAC /* srcMac */,
+ ns.ethHdr.srcMac /* dstMac */, ROUTER_LINK_LOCAL /* srcIp */,
+ ns.ipv6Hdr.srcIp /* dstIp */, flag, ROUTER_LINK_LOCAL /* target */);
+ mPacketReader.sendResponse(na);
+ assertNeverNotifyNeighborLost();
+ }
+
+ @Test
+ public void testIpReachabilityMonitor_mcastResoclicitProbeReachableWithDiffLinkLayerAddress()
+ throws Exception {
+ prepareIpReachabilityMonitorTest(true /* isMulticastResolicitEnabled */);
+
+ final NeighborSolicitation ns = waitForUnicastNeighborSolicitation(ROUTER_MAC /* dstMac */,
+ ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+
+ // Reply Neighbor Advertisement with a different link-layer address and check notifyLost
+ // callback will be triggered. Override flag must be set, which indicates that the
+ // advertisement should override an existing cache entry and update the cached link-layer
+ // address, otherwise, kernel won't transit to REACHABLE state with a different link-layer
+ // address.
+ int flag = NEIGHBOR_ADVERTISEMENT_FLAG_ROUTER | NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED
+ | NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE;
+ final MacAddress newMac = MacAddress.fromString("00:1a:11:22:33:55");
+ final ByteBuffer na = NeighborAdvertisement.build(newMac /* srcMac */,
+ ns.ethHdr.srcMac /* dstMac */, ROUTER_LINK_LOCAL /* srcIp */,
+ ns.ipv6Hdr.srcIp /* dstIp */, flag, ROUTER_LINK_LOCAL /* target */);
+ mPacketReader.sendResponse(na);
+ assertNotifyNeighborLost(ROUTER_LINK_LOCAL /* targetIp */);
+ }
+
+ @Test
+ public void testIPv6LinkLocalOnly() throws Exception {
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIPv4()
+ .withIpv6LinkLocalOnly()
+ .withRandomMacAddress()
+ .build();
+ startIpClientProvisioning(config);
+
+ final ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture());
+ final LinkProperties lp = captor.getValue();
+ assertNotNull(lp);
+ assertEquals(0, lp.getDnsServers().size());
+ final List<LinkAddress> addresses = lp.getLinkAddresses();
+ assertEquals(1, addresses.size());
+ assertTrue(addresses.get(0).getAddress().isLinkLocalAddress());
+ assertEquals(1, lp.getRoutes().size());
+ final RouteInfo route = lp.getRoutes().get(0);
+ assertNotNull(route);
+ assertTrue(route.getDestination().equals(new IpPrefix("fe80::/64")));
+ assertTrue(route.getGateway().isAnyLocalAddress());
+ }
+
+ @Test
+ public void testIPv6LinkLocalOnly_enableBothIPv4andIPv6LinkLocalOnly() throws Exception {
+ assertThrows(IllegalArgumentException.class,
+ () -> new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .withIpv6LinkLocalOnly()
+ .withRandomMacAddress()
+ .build()
+ );
+ }
}
diff --git a/tests/integration/src/android/net/ip/IpClientRootTest.kt b/tests/integration/src/android/net/ip/IpClientRootTest.kt
index ea2ec11..d861639 100644
--- a/tests/integration/src/android/net/ip/IpClientRootTest.kt
+++ b/tests/integration/src/android/net/ip/IpClientRootTest.kt
@@ -26,13 +26,14 @@
import android.net.ipmemorystore.NetworkAttributes
import android.net.ipmemorystore.Status
import android.net.networkstack.TestNetworkStackServiceClient
-import android.net.util.NetworkStackUtils
import android.os.Process
import android.provider.DeviceConfig
import android.util.ArrayMap
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.net.module.util.DeviceConfigUtils
import java.lang.System.currentTimeMillis
+import java.net.Inet6Address
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
@@ -45,6 +46,8 @@
import org.junit.AfterClass
import org.junit.BeforeClass
import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.never
import org.mockito.Mockito.timeout
import org.mockito.Mockito.verify
@@ -150,6 +153,7 @@
IIpClientCallbacks.Stub(), IIpClientCallbacks by base {
// asBinder is implemented by both base class and delegate: specify explicitly
override fun asBinder() = super.asBinder()
+ override fun getInterfaceVersion() = IIpClientCallbacks.VERSION
}
@After
@@ -194,37 +198,33 @@
return ipClientCaptor.value
}
- override fun setDhcpFeatures(
- isDhcpLeaseCacheEnabled: Boolean,
- isRapidCommitEnabled: Boolean,
- isDhcpIpConflictDetectEnabled: Boolean,
- isIPv6OnlyPreferredEnabled: Boolean
- ) {
+ override fun setFeatureEnabled(feature: String, enabled: Boolean) {
automation.adoptShellPermissionIdentity(READ_DEVICE_CONFIG, WRITE_DEVICE_CONFIG)
try {
- setFeatureEnabled(NetworkStackUtils.DHCP_INIT_REBOOT_VERSION, isDhcpLeaseCacheEnabled)
- setFeatureEnabled(NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION, isRapidCommitEnabled)
- setFeatureEnabled(NetworkStackUtils.DHCP_IP_CONFLICT_DETECT_VERSION,
- isDhcpIpConflictDetectEnabled)
- setFeatureEnabled(NetworkStackUtils.DHCP_IPV6_ONLY_PREFERRED_VERSION,
- isIPv6OnlyPreferredEnabled)
+ // Do not use computeIfAbsent as it would overwrite null values (flag originally unset)
+ if (!originalFlagValues.containsKey(feature)) {
+ originalFlagValues[feature] =
+ DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, feature)
+ }
+ // The feature is enabled if the flag is lower than the package version.
+ // Package versions follow a standard format with 9 digits.
+ // TODO: consider resetting flag values on reboot when set to special values like "1" or
+ // "999999999"
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, feature,
+ if (enabled) "1" else "999999999", false)
} finally {
automation.dropShellPermissionIdentity()
}
}
- private fun setFeatureEnabled(feature: String, enabled: Boolean) {
- // Do not use computeIfAbsent as it would overwrite null values (flag originally unset)
- if (!originalFlagValues.containsKey(feature)) {
- originalFlagValues[feature] =
- DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, feature)
+ override fun isFeatureEnabled(name: String, defaultEnabled: Boolean): Boolean {
+ automation.adoptShellPermissionIdentity(READ_DEVICE_CONFIG, WRITE_DEVICE_CONFIG)
+ try {
+ return DeviceConfigUtils.isFeatureEnabled(mContext, DeviceConfig.NAMESPACE_CONNECTIVITY,
+ name, defaultEnabled)
+ } finally {
+ automation.dropShellPermissionIdentity()
}
- // The feature is enabled if the flag is lower than the package version.
- // Package versions follow a standard format with 9 digits.
- // TODO: consider resetting flag values on reboot when set to special values like "1" or
- // "999999999"
- DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CONNECTIVITY, feature,
- if (enabled) "1" else "999999999", false)
}
private class TestAttributesRetrievedListener : OnNetworkAttributesRetrievedListener {
@@ -264,4 +264,16 @@
mStore.retrieveNetworkAttributes(l2Key, listener)
assertNull(listener.getBlockingNetworkAttributes(timeout))
}
+
+ override fun assertNotifyNeighborLost(targetIp: Inet6Address) {
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onReachabilityLost(anyString())
+ }
+
+ override fun assertNeverNotifyNeighborLost() {
+ verify(mCb, never()).onReachabilityLost(anyString())
+ }
+
+ override fun storeNetworkAttributes(l2Key: String, na: NetworkAttributes) {
+ mStore.storeNetworkAttributes(l2Key, na, null /* listener */)
+ }
}
diff --git a/tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java b/tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java
index e474d8a..0329fab 100644
--- a/tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java
+++ b/tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net.netlink;
+package com.android.net.module.util.netlink;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
diff --git a/tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt b/tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt
index 7e544ea..0ec43a5 100644
--- a/tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt
+++ b/tests/integration/src/android/net/util/NetworkStackUtilsIntegrationTest.kt
@@ -19,6 +19,7 @@
import android.Manifest.permission.MANAGE_TEST_NETWORKS
import android.content.Context
import android.net.InetAddresses.parseNumericAddress
+import android.net.IpPrefix
import android.net.MacAddress
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
@@ -26,12 +27,22 @@
import android.os.HandlerThread
import android.system.Os
import android.system.OsConstants.AF_INET
+import android.system.OsConstants.AF_PACKET
+import android.system.OsConstants.ARPHRD_ETHER
+import android.system.OsConstants.ETH_P_IPV6
import android.system.OsConstants.IPPROTO_UDP
import android.system.OsConstants.SOCK_DGRAM
import android.system.OsConstants.SOCK_NONBLOCK
import androidx.test.platform.app.InstrumentationRegistry
+import android.system.OsConstants.SOCK_RAW
+import android.system.OsConstants.SOL_SOCKET
+import android.system.OsConstants.SO_RCVTIMEO
+import android.system.StructTimeval
+import com.android.net.module.util.Ipv6Utils
import com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN
import com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY
+import com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST
+import com.android.net.module.util.structs.PrefixInformationOption
import com.android.testutils.ArpRequestFilter
import com.android.testutils.ETHER_HEADER_LENGTH
import com.android.testutils.IPV4_HEADER_LENGTH
@@ -42,9 +53,13 @@
import org.junit.Assert.assertArrayEquals
import org.junit.Before
import org.junit.Test
+import java.io.FileDescriptor
import java.net.Inet4Address
import kotlin.reflect.KClass
+import java.net.Inet6Address
+import java.nio.ByteBuffer
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
import kotlin.test.fail
class NetworkStackUtilsIntegrationTest {
@@ -52,8 +67,12 @@
private val context by lazy { inst.context }
private val TEST_TIMEOUT_MS = 10_000L
+ private val TEST_MTU = 1500
private val TEST_TARGET_IPV4_ADDR = parseNumericAddress("192.0.2.42") as Inet4Address
+ private val TEST_SRC_MAC = MacAddress.fromString("BA:98:76:54:32:10")
private val TEST_TARGET_MAC = MacAddress.fromString("01:23:45:67:89:0A")
+ private val TEST_INET6ADDR_1 = parseNumericAddress("2001:db8::1") as Inet6Address
+ private val TEST_INET6ADDR_2 = parseNumericAddress("2001:db8::2") as Inet6Address
private val readerHandler = HandlerThread(
NetworkStackUtilsIntegrationTest::class.java.simpleName)
@@ -103,8 +122,7 @@
null /* hostname */, false /* metered */, 1500 /* mtu */,
null /* captivePortalUrl */)
// Not using .array as per errorprone "ByteBufferBackingArray" recommendation
- val originalPacket = ByteArray(buffer.limit())
- buffer.get(originalPacket)
+ val originalPacket = buffer.readAsArray()
Os.sendto(socket, originalPacket, 0 /* bytesOffset */, originalPacket.size /* bytesCount */,
0 /* flags */, TEST_TARGET_IPV4_ADDR, DhcpPacket.DHCP_CLIENT.toInt() /* port */)
@@ -112,7 +130,7 @@
// Verify the packet was sent to the mac address specified in the ARP entry
// Also accept ARP requests, but expect that none is sent before the UDP packet
// IPv6 NS may be sent on the interface but will be filtered out
- val sentPacket = reader.popPacket(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter()))
+ val sentPacket = reader.poll(TEST_TIMEOUT_MS, IPv4UdpFilter().or(ArpRequestFilter()))
?: fail("Packet was not sent on the interface")
val sentTargetAddr = MacAddress.fromBytes(sentPacket.copyOfRange(0, ETHER_ADDR_LEN))
@@ -123,7 +141,55 @@
assertArrayEquals("Sent packet != original packet", originalPacket, sentDhcpPacket)
}
+
+ @Test
+ fun testAttachRaFilter() {
+ val socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6)
+ val ifParams = InterfaceParams.getByName(iface.interfaceName)
+ ?: fail("Could not obtain interface params for ${iface.interfaceName}")
+ val socketAddr = SocketUtils.makePacketSocketAddress(ETH_P_IPV6, ifParams.index)
+ Os.bind(socket, socketAddr)
+ Os.setsockoptTimeval(socket, SOL_SOCKET, SO_RCVTIMEO,
+ StructTimeval.fromMillis(TEST_TIMEOUT_MS))
+
+ // Verify that before setting any filter, the socket receives pings
+ val echo = Ipv6Utils.buildEchoRequestPacket(TEST_SRC_MAC, TEST_TARGET_MAC, TEST_INET6ADDR_1,
+ TEST_INET6ADDR_2)
+ reader.sendResponse(echo)
+ echo.rewind()
+ assertNextPacketEquals(socket, echo.readAsArray(), "ICMPv6 echo")
+
+ NetworkStackUtils.attachRaFilter(socket, ARPHRD_ETHER)
+ // Send another echo, then an RA. After setting the filter expect only the RA.
+ echo.rewind()
+ reader.sendResponse(echo)
+ val pio = PrefixInformationOption.build(IpPrefix("2001:db8:1::/64"),
+ 0.toByte() /* flags */, 3600 /* validLifetime */, 1800 /* preferredLifetime */)
+ val ra = Ipv6Utils.buildRaPacket(TEST_SRC_MAC, TEST_TARGET_MAC,
+ TEST_INET6ADDR_1 /* routerAddr */, IPV6_ADDR_ALL_NODES_MULTICAST,
+ 0.toByte() /* flags */, 1800 /* lifetime */, 0 /* reachableTime */,
+ 0 /* retransTimer */, pio)
+ reader.sendResponse(ra)
+ ra.rewind()
+
+ assertNextPacketEquals(socket, ra.readAsArray(), "ICMPv6 RA")
+ }
+
+ private fun assertNextPacketEquals(socket: FileDescriptor, expected: ByteArray, descr: String) {
+ val buffer = ByteArray(TEST_MTU)
+ val readPacket = Os.read(socket, buffer, 0 /* byteOffset */, buffer.size)
+ assertTrue(readPacket > 0, "$descr not received")
+ assertEquals(expected.size, readPacket, "Received packet size does not match for $descr")
+ assertArrayEquals("Received packet != expected $descr",
+ expected, buffer.copyOfRange(0, readPacket))
+ }
+}
+
+private fun ByteBuffer.readAsArray(): ByteArray {
+ val out = ByteArray(remaining())
+ get(out)
+ return out
}
private fun <T : Any> Context.assertHasService(manager: KClass<T>) = getSystemService(manager.java)
- ?: fail("Could not find service $manager")
\ No newline at end of file
+ ?: fail("Could not find service $manager")
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index eb52f92..fa054fe 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_defaults {
name: "NetworkStackTestsDefaults",
platform_apis: true,
@@ -32,7 +36,10 @@
"android.test.base",
"android.test.mock",
],
- defaults: ["libnetworkstackutilsjni_deps"],
+ defaults: [
+ "framework-connectivity-test-defaults",
+ "libnetworkstackutilsjni_deps"
+ ],
jni_libs: [
// For mockito extended
"libdexmakerjvmtiagent",
@@ -40,7 +47,6 @@
"libnetworkstackutilsjni",
],
jni_uses_sdk_apis: true,
- jarjar_rules: ":NetworkStackJarJarRules",
}
// Tests for NetworkStackNext.
@@ -54,7 +60,7 @@
defaults: ["NetworkStackTestsDefaults"],
static_libs: ["NetworkStackApiCurrentLib"],
compile_multilib: "both", // Workaround for b/147785146 for mainline-presubmit
- enabled: false, // Disabled in mainline-prod
+ jarjar_rules: ":NetworkStackJarJarRules",
}
// Library containing the unit tests. This is used by the coverage test target to pull in the
@@ -67,8 +73,8 @@
static_libs: ["NetworkStackApiStableLib"],
visibility: [
"//packages/modules/NetworkStack/tests/integration",
- "//frameworks/base/packages/Tethering/tests/integration",
- "//packages/modules/Connectivity/Tethering/tests/integration",
+ "//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
]
}
@@ -81,6 +87,7 @@
defaults: ["NetworkStackTestsDefaults"],
static_libs: ["NetworkStackApiStableLib"],
compile_multilib: "both",
+ jarjar_rules: ":NetworkStackJarJarRules",
}
// Additional dependencies of libnetworkstackutilsjni that are not provided by the system when
diff --git a/tests/unit/jni/Android.bp b/tests/unit/jni/Android.bp
index fa1f420..0c9087f 100644
--- a/tests/unit/jni/Android.bp
+++ b/tests/unit/jni/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_library_shared {
name: "libnetworkstacktestsjni",
srcs: [
diff --git a/tests/unit/lint-baseline.xml b/tests/unit/lint-baseline.xml
new file mode 100644
index 0000000..0bfcaa9
--- /dev/null
+++ b/tests/unit/lint-baseline.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+ errorLine1=" private val EMPTY_CAPABILITIES = NetworkCapabilities()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt"
+ line="134"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+ errorLine1=" private val VALIDATED_CAPABILITIES = NetworkCapabilities()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt"
+ line="135"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+ errorLine1=" new NetworkCapabilities()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java"
+ line="57"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+ errorLine1=" NetworkCapabilities nc = new NetworkCapabilities();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java"
+ line="109"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+ errorLine1=" nc = new NetworkCapabilities();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java"
+ line="117"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+ errorLine1=" nc = new NetworkCapabilities();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java"
+ line="123"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+ errorLine1=" nc = new NetworkCapabilities();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/NetworkStack/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java"
+ line="129"
+ column="14"/>
+ </issue>
+
+</issues>
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index 416a6c3..b6de3a1 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -1056,6 +1056,10 @@
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
private static final byte[] IPV6_ALL_ROUTERS_ADDRESS =
{ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 };
+ private static final byte[] IPV6_SOLICITED_NODE_MULTICAST_ADDRESS = {
+ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ (byte) 0xff, (byte) 0xab, (byte) 0xcd, (byte) 0xef,
+ };
private static final int ICMP6_TYPE_OFFSET = IP_HEADER_OFFSET + IPV6_HEADER_LEN;
private static final int ICMP6_ROUTER_SOLICITATION = 133;
@@ -1241,6 +1245,14 @@
put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_NODES_ADDRESS);
assertDrop(program, packet.array());
+ // Verify ICMPv6 NA to ff02::2 is dropped
+ put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_ALL_ROUTERS_ADDRESS);
+ assertDrop(program, packet.array());
+
+ // Verify ICMPv6 NA to Solicited-Node Multicast is passed
+ put(packet, IPV6_DEST_ADDR_OFFSET, IPV6_SOLICITED_NODE_MULTICAST_ADDRESS);
+ assertPass(program, packet.array());
+
// Verify ICMPv6 RS to any is dropped
packet.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_SOLICITATION);
assertDrop(program, packet.array());
diff --git a/tests/unit/src/android/net/dhcp/DhcpPacketTest.java b/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
index d0c49d3..1a1f6c3 100644
--- a/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
+++ b/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
@@ -96,12 +96,12 @@
@Before
public void setUp() {
- DhcpPacket.testOverrideVendorId = "android-dhcp-???";
+ DhcpPacket.sTestOverrideVendorId = "android-dhcp-???";
}
@After
public void tearDown() {
- DhcpPacket.testOverrideVendorId = null;
+ DhcpPacket.sTestOverrideVendorId = null;
}
class TestDhcpPacket extends DhcpPacket {
diff --git a/tests/unit/src/android/net/ip/ConntrackMonitorTest.java b/tests/unit/src/android/net/ip/ConntrackMonitorTest.java
index 6e9078e..fc0d52b 100644
--- a/tests/unit/src/android/net/ip/ConntrackMonitorTest.java
+++ b/tests/unit/src/android/net/ip/ConntrackMonitorTest.java
@@ -16,15 +16,16 @@
package android.net.ip;
import static android.net.ip.ConntrackMonitor.ConntrackEvent;
-import static android.net.netlink.ConntrackMessage.Tuple;
-import static android.net.netlink.ConntrackMessage.TupleIpv4;
-import static android.net.netlink.ConntrackMessage.TupleProto;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.SOCK_DGRAM;
+import static com.android.net.module.util.netlink.ConntrackMessage.Tuple;
+import static com.android.net.module.util.netlink.ConntrackMessage.TupleIpv4;
+import static com.android.net.module.util.netlink.ConntrackMessage.TupleProto;
+import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
+import static com.android.net.module.util.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
@@ -33,8 +34,6 @@
import static org.mockito.Mockito.verify;
import android.net.InetAddresses;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkSocket;
import android.net.util.SharedLog;
import android.os.ConditionVariable;
import android.os.Handler;
@@ -46,6 +45,9 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.netlink.NetlinkConstants;
+import com.android.net.module.util.netlink.NetlinkSocket;
+
import libcore.util.HexEncoding;
import org.junit.After;
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java
index e991ea7..95fe93a 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -18,12 +18,15 @@
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import static org.junit.Assert.assertArrayEquals;
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 static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -48,22 +51,32 @@
import android.net.MacAddress;
import android.net.NetworkStackIpMemoryStore;
import android.net.RouteInfo;
+import android.net.apf.ApfCapabilities;
+import android.net.apf.ApfFilter.ApfConfiguration;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.InitialConfiguration;
+import android.net.shared.Layer2Information;
import android.net.shared.ProvisioningConfiguration;
+import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import android.net.util.InterfaceParams;
+import android.os.Build;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.networkstack.R;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService;
import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.HandlerUtils;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -73,9 +86,12 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Random;
import java.util.Set;
@@ -85,6 +101,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpClientTest {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
private static final String VALID = "VALID";
private static final String INVALID = "INVALID";
private static final String TEST_IFNAME = "test_wlan0";
@@ -94,6 +113,9 @@
private static final int TEST_TIMEOUT_MS = 400;
private static final String TEST_L2KEY = "some l2key";
private static final String TEST_CLUSTER = "some cluster";
+ private static final String TEST_SSID = "test_ssid";
+ private static final String TEST_BSSID = "00:11:22:33:44:55";
+ private static final String TEST_BSSID2 = "00:1A:11:22:33:44";
private static final String TEST_GLOBAL_ADDRESS = "1234:4321::548d:2db2:4fcf:ef75/64";
private static final String[] TEST_LOCAL_ADDRESSES = {
@@ -409,6 +431,7 @@
@Test
public void testIsProvisioned() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
InitialConfiguration empty = conf(links(), prefixes());
IsProvisionedTestCase[] testcases = {
// nothing
@@ -440,7 +463,7 @@
};
for (IsProvisionedTestCase testcase : testcases) {
- if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
+ if (ipc.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
fail(testcase.errorMessage());
}
}
@@ -631,6 +654,183 @@
return out;
}
+ private ApfConfiguration verifyApfFilterCreatedOnStart(IpClient ipc) {
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIPv4()
+ .withoutIpReachabilityMonitor()
+ .withInitialConfiguration(
+ conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips()))
+ .withApfCapabilities(new ApfCapabilities(
+ 4 /* version */, 4096 /* maxProgramSize */, 4 /* format */))
+ .build();
+
+ ipc.startProvisioning(config);
+ final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass(
+ ApfConfiguration.class);
+ verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter(
+ any(), configCaptor.capture(), any(), any());
+
+ return configCaptor.getValue();
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.R)
+ public void testApfConfiguration_R() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertEquals(ApfCapabilities.getApfDrop8023Frames(), config.ieee802_3Filter);
+ assertArrayEquals(ApfCapabilities.getApfEtherTypeBlackList(), config.ethTypeBlackList);
+
+ verify(mResources, never()).getBoolean(R.bool.config_apfDrop802_3Frames);
+ verify(mResources, never()).getIntArray(R.array.config_apfEthTypeDenyList);
+
+ verifyShutdown(ipc);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testApfConfiguration() throws Exception {
+ doReturn(true).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames);
+ final int[] ethTypeDenyList = new int[] { 0x88A2, 0x88A4 };
+ doReturn(ethTypeDenyList).when(mResources).getIntArray(
+ R.array.config_apfEthTypeDenyList);
+
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertTrue(config.ieee802_3Filter);
+ assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList);
+
+ verifyShutdown(ipc);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testApfConfiguration_NoApfDrop8023Frames() throws Exception {
+ doReturn(false).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames);
+ final int[] ethTypeDenyList = new int[] { 0x88A3, 0x88A5 };
+ doReturn(ethTypeDenyList).when(mResources).getIntArray(
+ R.array.config_apfEthTypeDenyList);
+
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertFalse(config.ieee802_3Filter);
+ assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList);
+
+ verifyShutdown(ipc);
+ }
+
+ private ScanResultInfo makeScanResultInfo(final String ssid, final String bssid) {
+ final ByteBuffer payload = ByteBuffer.allocate(14 /* oui + type + data */);
+ final byte[] data = new byte[10];
+ new Random().nextBytes(data);
+ payload.put(new byte[] { 0x00, 0x1A, 0x11 });
+ payload.put((byte) 0x06);
+ payload.put(data);
+
+ final ScanResultInfo.InformationElement ie =
+ new ScanResultInfo.InformationElement(0xdd /* IE id */, payload);
+ return new ScanResultInfo(ssid, bssid, Collections.singletonList(ie));
+ }
+
+ @Test
+ public void testGetInitialBssidOnSOrAbove() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_BSSID));
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID2);
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+ true /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidOnSOrAbove_NullScanReqsultInfo() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_BSSID));
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* ScanResultInfo */,
+ true /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidOnSOrAbove_NullBssid() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ null /* bssid */);
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+ true /* isAtLeastS */);
+ assertNull(bssid);
+ }
+
+ @Test
+ public void testGetInitialBssidOnSOrAbove_NullLayer2Info() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+ final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+ true /* isAtLeastS */);
+ assertNull(bssid);
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_BSSID2));
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+ false /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS_NullLayer2Info() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID);
+ final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+ false /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS_BrokenInitialBssid() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:");
+ final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo,
+ false /* isAtLeastS */);
+ assertNull(bssid);
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS_BrokenInitialBssidFallback() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_BSSID));
+ final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:");
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo,
+ false /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS_NullScanResultInfoFallback() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+ MacAddress.fromString(TEST_BSSID));
+ final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* scanResultInfo */,
+ false /* isAtLeastS */);
+ assertEquals(bssid, MacAddress.fromString(TEST_BSSID));
+ }
+
+ @Test
+ public void testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */,
+ null /* scanResultInfo */, false /* isAtLeastS */);
+ assertNull(bssid);
+ }
+
interface Fn<A,B> {
B call(A a) throws Exception;
}
diff --git a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
index 863e268..ea8f1da 100644
--- a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
+++ b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
@@ -16,6 +16,7 @@
package android.net.ip
import android.content.Context
+import android.net.ip.IpNeighborMonitor.NeighborEventConsumer
import android.net.INetd
import android.net.InetAddresses.parseNumericAddress
import android.net.IpPrefix
@@ -23,19 +24,37 @@
import android.net.LinkProperties
import android.net.RouteInfo
import android.net.metrics.IpConnectivityLog
-import android.net.netlink.StructNdMsg.NUD_FAILED
-import android.net.netlink.StructNdMsg.NUD_STALE
-import android.net.netlink.makeNewNeighMessage
import android.net.util.InterfaceParams
+import android.net.util.NetworkStackUtils.IP_REACHABILITY_MCAST_RESOLICIT_VERSION
import android.net.util.SharedLog
import android.os.Handler
import android.os.HandlerThread
import android.os.MessageQueue
import android.os.MessageQueue.OnFileDescriptorEventListener
+import android.stats.connectivity.IpType
+import android.stats.connectivity.IpType.IPV4
+import android.stats.connectivity.IpType.IPV6
+import android.stats.connectivity.NudEventType
+import android.stats.connectivity.NudEventType.NUD_CONFIRM_FAILED
+import android.stats.connectivity.NudEventType.NUD_CONFIRM_FAILED_CRITICAL
+import android.stats.connectivity.NudEventType.NUD_MAC_ADDRESS_CHANGED
+import android.stats.connectivity.NudEventType.NUD_POST_ROAMING_FAILED
+import android.stats.connectivity.NudEventType.NUD_POST_ROAMING_FAILED_CRITICAL
+import android.stats.connectivity.NudEventType.NUD_ORGANIC_FAILED
+import android.stats.connectivity.NudEventType.NUD_ORGANIC_FAILED_CRITICAL
+import android.stats.connectivity.NudNeighborType
+import android.stats.connectivity.NudNeighborType.NUD_NEIGHBOR_BOTH
+import android.stats.connectivity.NudNeighborType.NUD_NEIGHBOR_DNS
+import android.stats.connectivity.NudNeighborType.NUD_NEIGHBOR_GATEWAY
import android.system.ErrnoException
import android.system.OsConstants.EAGAIN
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
+import com.android.networkstack.metrics.IpReachabilityMonitorMetrics
+import com.android.net.module.util.netlink.StructNdMsg.NUD_FAILED
+import com.android.net.module.util.netlink.StructNdMsg.NUD_REACHABLE
+import com.android.net.module.util.netlink.StructNdMsg.NUD_STALE
+import com.android.testutils.makeNewNeighMessage
import com.android.testutils.waitForIdle
import org.junit.After
import org.junit.Before
@@ -43,12 +62,15 @@
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyObject
import org.mockito.ArgumentMatchers.anyString
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.timeout
import org.mockito.Mockito.verify
import java.io.FileDescriptor
@@ -66,12 +88,20 @@
private val TEST_IPV4_GATEWAY = parseNumericAddress("192.168.222.3") as Inet4Address
private val TEST_IPV6_GATEWAY = parseNumericAddress("2001:db8::1") as Inet6Address
+// IPv4 gateway is also DNS server.
+private val TEST_IPV4_GATEWAY_DNS = parseNumericAddress("192.168.222.100") as Inet4Address
+
private val TEST_IPV4_LINKADDR = LinkAddress("192.168.222.123/24")
private val TEST_IPV6_LINKADDR = LinkAddress("2001:db8::123/64")
+private val TEST_IPV6_LINKLOCAL_LINKADDR = LinkAddress("fe80::123/64")
+private val TEST_IPV6_LINKLOCAL_GATEWAY = parseNumericAddress("fe80::1") as Inet6Address
+private val TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY = parseNumericAddress("fe80::1%21") as Inet6Address
+
// DNSes inside IP prefix
private val TEST_IPV4_DNS = parseNumericAddress("192.168.222.1") as Inet4Address
private val TEST_IPV6_DNS = parseNumericAddress("2001:db8::321") as Inet6Address
+private val TEST_IPV6_DNS2 = parseNumericAddress("2001:db8::456") as Inet6Address
private val TEST_IFACE = InterfaceParams("fake0", 21, null)
private val TEST_LINK_PROPERTIES = LinkProperties().apply {
@@ -91,6 +121,54 @@
addDnsServer(TEST_IPV6_DNS)
}
+private val TEST_IPV4_ONLY_LINK_PROPERTIES = LinkProperties().apply {
+ interfaceName = TEST_IFACE.name
+ addLinkAddress(TEST_IPV4_LINKADDR)
+
+ // Add on link routes
+ addRoute(RouteInfo(TEST_IPV4_LINKADDR, null /* gateway */, TEST_IFACE.name))
+
+ // Add default routes
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY_DNS))
+
+ addDnsServer(TEST_IPV4_GATEWAY_DNS)
+}
+
+private val TEST_IPV6_LINKLOCAL_SCOPED_LINK_PROPERTIES = LinkProperties().apply {
+ interfaceName = TEST_IFACE.name
+ addLinkAddress(TEST_IPV6_LINKADDR)
+ addLinkAddress(TEST_IPV6_LINKLOCAL_LINKADDR)
+
+ // Add on link routes
+ addRoute(RouteInfo(TEST_IPV6_LINKADDR, null /* gateway */, TEST_IFACE.name))
+ addRoute(RouteInfo(TEST_IPV6_LINKLOCAL_LINKADDR, null /* gateway */, TEST_IFACE.name))
+
+ // Add default routes
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY))
+
+ addDnsServer(TEST_IPV6_DNS)
+}
+
+private val TEST_DUAL_LINK_PROPERTIES = LinkProperties().apply {
+ interfaceName = TEST_IFACE.name
+ addLinkAddress(TEST_IPV4_LINKADDR)
+ addLinkAddress(TEST_IPV6_LINKADDR)
+ addLinkAddress(TEST_IPV6_LINKLOCAL_LINKADDR)
+
+ // Add on link routes
+ addRoute(RouteInfo(TEST_IPV4_LINKADDR, null /* gateway */, TEST_IFACE.name))
+ addRoute(RouteInfo(TEST_IPV6_LINKADDR, null /* gateway */, TEST_IFACE.name))
+ addRoute(RouteInfo(TEST_IPV6_LINKLOCAL_LINKADDR, null /* gateway */, TEST_IFACE.name))
+
+ // Add default routes
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("0.0.0.0"), 0), TEST_IPV4_GATEWAY))
+ addRoute(RouteInfo(IpPrefix(parseNumericAddress("::"), 0), TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY))
+
+ addDnsServer(TEST_IPV4_DNS)
+ addDnsServer(TEST_IPV6_DNS)
+ addDnsServer(TEST_IPV6_DNS2)
+}
+
/**
* Tests for IpReachabilityMonitor.
*/
@@ -104,6 +182,7 @@
private val netd = mock(INetd::class.java)
private val fd = mock(FileDescriptor::class.java)
private val metricsLog = mock(IpConnectivityLog::class.java)
+ private val mIpReachabilityMonitorMetrics = mock(IpReachabilityMonitorMetrics::class.java)
private val handlerThread = HandlerThread(IpReachabilityMonitorTest::class.simpleName)
private val handler by lazy { Handler(handlerThread.looper) }
@@ -171,6 +250,8 @@
neighborMonitor = TestIpNeighborMonitor(handler, log, cb, fd)
neighborMonitor
}.`when`(dependencies).makeIpNeighborMonitor(any(), any(), any())
+ doReturn(mIpReachabilityMonitorMetrics)
+ .`when`(dependencies).getIpReachabilityMonitorMetrics()
val monitorFuture = CompletableFuture<IpReachabilityMonitor>()
// IpReachabilityMonitor needs to be started from the handler thread
@@ -207,8 +288,8 @@
verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(TEST_IPV4_DNS), anyString())
}
- private fun runLoseProvisioningTest(lostNeighbor: InetAddress) {
- reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES)
+ private fun runLoseProvisioningTest(newLp: LinkProperties, lostNeighbor: InetAddress) {
+ reachabilityMonitor.updateLinkProperties(newLp)
neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_GATEWAY, NUD_STALE))
neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_GATEWAY, NUD_STALE))
@@ -219,23 +300,261 @@
verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(lostNeighbor), anyString())
}
+ private fun verifyNudFailureMetrics(
+ eventType: NudEventType,
+ ipType: IpType,
+ lostNeighborType: NudNeighborType
+ ) {
+ verify(mIpReachabilityMonitorMetrics, timeout(TEST_TIMEOUT_MS)).setNudIpType(eq(ipType))
+ verify(mIpReachabilityMonitorMetrics, timeout(TEST_TIMEOUT_MS))
+ .setNudEventType(eq(eventType))
+ verify(mIpReachabilityMonitorMetrics, timeout(TEST_TIMEOUT_MS))
+ .setNudNeighborType(eq(lostNeighborType))
+ }
+
+ // Verify if the notifyLost will be called when one neighbor has lost but it's still
+ // provisioned.
+ private fun runLoseNeighborStillProvisionedTest(
+ newLp: LinkProperties,
+ lostNeighbor: InetAddress,
+ eventType: NudEventType,
+ ipType: IpType,
+ lostNeighborType: NudNeighborType
+ ) {
+ reachabilityMonitor.updateLinkProperties(newLp)
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(lostNeighbor, NUD_FAILED))
+ handlerThread.waitForIdle(TEST_TIMEOUT_MS)
+ verify(callback, never()).notifyLost(any(), anyString())
+ verifyNudFailureMetrics(eventType, ipType, lostNeighborType)
+ }
+
+ private fun runNeighborReachableButMacAddrChangedTest(
+ newLp: LinkProperties,
+ neighbor: InetAddress,
+ ipType: IpType
+ ) {
+ doReturn(true).`when`(dependencies).isFeatureEnabled(anyObject(),
+ eq(IP_REACHABILITY_MCAST_RESOLICIT_VERSION), anyBoolean())
+
+ reachabilityMonitor.updateLinkProperties(newLp)
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(neighbor, NUD_REACHABLE,
+ "001122334455" /* oldMac */))
+ handlerThread.waitForIdle(TEST_TIMEOUT_MS)
+ verify(callback, never()).notifyLost(eq(neighbor), anyString())
+
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+
+ neighborMonitor.enqueuePacket(makeNewNeighMessage(neighbor, NUD_REACHABLE,
+ "1122334455aa" /* newMac */))
+ verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(neighbor), anyString())
+ verifyNudFailureMetrics(NUD_MAC_ADDRESS_CHANGED, ipType, NUD_NEIGHBOR_GATEWAY)
+ }
+
@Test
fun testLoseProvisioning_Ipv4DnsLost() {
- runLoseProvisioningTest(TEST_IPV4_DNS)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV4_DNS)
}
@Test
fun testLoseProvisioning_Ipv6DnsLost() {
- runLoseProvisioningTest(TEST_IPV6_DNS)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_DNS)
}
@Test
fun testLoseProvisioning_Ipv4GatewayLost() {
- runLoseProvisioningTest(TEST_IPV4_GATEWAY)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY)
}
@Test
fun testLoseProvisioning_Ipv6GatewayLost() {
- runLoseProvisioningTest(TEST_IPV6_GATEWAY)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY)
}
-}
\ No newline at end of file
+
+ private fun runNudProbeFailureMetricsTest(
+ lp: LinkProperties,
+ lostNeighbor: InetAddress,
+ eventType: NudEventType,
+ ipType: IpType,
+ lostNeighborType: NudNeighborType
+ ) {
+ runLoseProvisioningTest(lp, lostNeighbor)
+ verifyNudFailureMetrics(eventType, ipType, lostNeighborType)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv6GatewayLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY,
+ NUD_POST_ROAMING_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv4GatewayLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY,
+ NUD_POST_ROAMING_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv6DnsLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_POST_ROAMING_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv4DnsLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_DNS,
+ NUD_POST_ROAMING_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv4BothGatewayAndDnsLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_IPV4_ONLY_LINK_PROPERTIES, TEST_IPV4_GATEWAY_DNS,
+ NUD_POST_ROAMING_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_BOTH)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6LinklocalScopedGatewayLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_IPV6_LINKLOCAL_SCOPED_LINK_PROPERTIES,
+ TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY, NUD_POST_ROAMING_FAILED_CRITICAL, IPV6,
+ NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv6GatewayLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY,
+ NUD_CONFIRM_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv4GatewayLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY,
+ NUD_CONFIRM_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv6DnsLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_CONFIRM_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_Ipv4DnsLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_DNS,
+ NUD_CONFIRM_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv4BothGatewayAndDnsLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_IPV4_ONLY_LINK_PROPERTIES, TEST_IPV4_GATEWAY_DNS,
+ NUD_CONFIRM_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_BOTH)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6LinklocalScopedGatewayLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runNudProbeFailureMetricsTest(TEST_IPV6_LINKLOCAL_SCOPED_LINK_PROPERTIES,
+ TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY, NUD_CONFIRM_FAILED_CRITICAL, IPV6,
+ NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6GatewayLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY,
+ NUD_ORGANIC_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv4GatewayLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY,
+ NUD_ORGANIC_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6DnsLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_ORGANIC_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv4DnsLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_LINK_PROPERTIES, TEST_IPV4_DNS,
+ NUD_ORGANIC_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv4BothGatewayAndDnsLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_IPV4_ONLY_LINK_PROPERTIES, TEST_IPV4_GATEWAY_DNS,
+ NUD_ORGANIC_FAILED_CRITICAL, IPV4, NUD_NEIGHBOR_BOTH)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6LinklocalScopedGatewayLostOrganic() {
+ runNudProbeFailureMetricsTest(TEST_IPV6_LINKLOCAL_SCOPED_LINK_PROPERTIES,
+ TEST_IPV6_LINKLOCAL_SCOPED_GATEWAY, NUD_ORGANIC_FAILED_CRITICAL, IPV6,
+ NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6OneDnsNeighborLostPostRoaming() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runLoseNeighborStillProvisionedTest(TEST_DUAL_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_POST_ROAMING_FAILED, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6OneDnsNeighborLostAfterConfirm() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runLoseNeighborStillProvisionedTest(TEST_DUAL_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_CONFIRM_FAILED, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_IPv6OneDnsNeighborLostOrganic() {
+ runLoseNeighborStillProvisionedTest(TEST_DUAL_LINK_PROPERTIES, TEST_IPV6_DNS,
+ NUD_ORGANIC_FAILED, IPV6, NUD_NEIGHBOR_DNS)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_multipleProbesFromRoamFirst() {
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ handlerThread.waitForIdle(TEST_TIMEOUT_MS)
+ Thread.sleep(2)
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY)
+
+ verifyNudFailureMetrics(NUD_POST_ROAMING_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_multipleProbesFromConfirmFirst() {
+ reachabilityMonitor.probeAll(false /* dueToRoam */)
+ handlerThread.waitForIdle(TEST_TIMEOUT_MS)
+ Thread.sleep(2)
+ reachabilityMonitor.probeAll(true /* dueToRoam */)
+ runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY)
+
+ verifyNudFailureMetrics(NUD_CONFIRM_FAILED_CRITICAL, IPV6, NUD_NEIGHBOR_GATEWAY)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_defaultIPv6GatewayMacAddrChanged() {
+ runNeighborReachableButMacAddrChangedTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY, IPV6)
+ }
+
+ @Test
+ fun testNudProbeFailedMetrics_defaultIPv4GatewayMacAddrChanged() {
+ runNeighborReachableButMacAddrChangedTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY, IPV4)
+ }
+}
diff --git a/tests/unit/src/android/net/netlink/ConntrackMessageTest.java b/tests/unit/src/android/net/netlink/ConntrackMessageTest.java
deleted file mode 100644
index 2e8d184..0000000
--- a/tests/unit/src/android/net/netlink/ConntrackMessageTest.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2017 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.netlink;
-
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
-import static android.net.netlink.NetlinkConstants.NFNL_SUBSYS_CTNETLINK;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
-
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ConntrackMessageTest {
- private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
-
- private short makeCtType(short msgType) {
- return (short) (NFNL_SUBSYS_CTNETLINK << 8 | (byte) msgType);
- }
-
- // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
- public static final String CT_V4UPDATE_TCP_HEX =
- // struct nlmsghdr
- "50000000" + // length = 80
- "0001" + // type = (1 << 8) | 0
- "0501" + // flags
- "01000000" + // seqno = 1
- "00000000" + // pid = 0
- // struct nfgenmsg
- "02" + // nfgen_family = AF_INET
- "00" + // version = NFNETLINK_V0
- "0000" + // res_id
- // struct nlattr
- "3400" + // nla_len = 52
- "0180" + // nla_type = nested CTA_TUPLE_ORIG
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
- "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6
- "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
- "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
- // struct nlattr
- "0800" + // nla_len = 8
- "0700" + // nla_type = CTA_TIMEOUT
- "00069780"; // nla_value = 432000 (big endian)
- public static final byte[] CT_V4UPDATE_TCP_BYTES =
- HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
-
- private byte[] makeIPv4TimeoutUpdateRequestTcp() throws Exception {
- return ConntrackMessage.newIPv4TimeoutUpdateRequest(
- OsConstants.IPPROTO_TCP,
- (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
- (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
- 432000);
- }
-
- // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
- public static final String CT_V4UPDATE_UDP_HEX =
- // struct nlmsghdr
- "50000000" + // length = 80
- "0001" + // type = (1 << 8) | 0
- "0501" + // flags
- "01000000" + // seqno = 1
- "00000000" + // pid = 0
- // struct nfgenmsg
- "02" + // nfgen_family = AF_INET
- "00" + // version = NFNETLINK_V0
- "0000" + // res_id
- // struct nlattr
- "3400" + // nla_len = 52
- "0180" + // nla_type = nested CTA_TUPLE_ORIG
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
- "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17
- "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
- "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
- // struct nlattr
- "0800" + // nla_len = 8
- "0700" + // nla_type = CTA_TIMEOUT
- "000000B4"; // nla_value = 180 (big endian)
- public static final byte[] CT_V4UPDATE_UDP_BYTES =
- HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
-
- private byte[] makeIPv4TimeoutUpdateRequestUdp() throws Exception {
- return ConntrackMessage.newIPv4TimeoutUpdateRequest(
- OsConstants.IPPROTO_UDP,
- (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
- (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
- 180);
- }
-
- @Test
- public void testConntrackMakeIPv4TcpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] tcp = makeIPv4TimeoutUpdateRequestTcp();
- assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
- }
-
- @Test
- public void testConntrackParseIPv4TcpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] tcp = makeIPv4TimeoutUpdateRequestTcp();
- final ByteBuffer byteBuffer = ByteBuffer.wrap(tcp);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
- assertNotNull(msg);
- assertTrue(msg instanceof ConntrackMessage);
- final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
-
- final StructNlMsgHdr hdr = conntrackMessage.getHeader();
- assertNotNull(hdr);
- assertEquals(80, hdr.nlmsg_len);
- assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
- assertEquals((short) (StructNlMsgHdr.NLM_F_REPLACE | StructNlMsgHdr.NLM_F_REQUEST
- | StructNlMsgHdr.NLM_F_ACK), hdr.nlmsg_flags);
- assertEquals(1, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
- assertNotNull(nfmsgHdr);
- assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
- assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
- assertEquals((short) 0, nfmsgHdr.res_id);
-
- assertEquals(InetAddress.parseNumericAddress("192.168.43.209"),
- conntrackMessage.tupleOrig.srcIp);
- assertEquals(InetAddress.parseNumericAddress("23.211.13.26"),
- conntrackMessage.tupleOrig.dstIp);
- assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleOrig.protoNum);
- assertEquals((short) 44333, conntrackMessage.tupleOrig.srcPort);
- assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
-
- assertNull(conntrackMessage.tupleReply);
-
- assertEquals(0 /* absent */, conntrackMessage.status);
- assertEquals(432000, conntrackMessage.timeoutSec);
- }
-
- @Test
- public void testConntrackMakeIPv4UdpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] udp = makeIPv4TimeoutUpdateRequestUdp();
- assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
- }
-
- @Test
- public void testConntrackParseIPv4UdpTimeoutUpdate() throws Exception {
- assumeTrue(USING_LE);
-
- final byte[] udp = makeIPv4TimeoutUpdateRequestUdp();
- final ByteBuffer byteBuffer = ByteBuffer.wrap(udp);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
- assertNotNull(msg);
- assertTrue(msg instanceof ConntrackMessage);
- final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
-
- final StructNlMsgHdr hdr = conntrackMessage.getHeader();
- assertNotNull(hdr);
- assertEquals(80, hdr.nlmsg_len);
- assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
- assertEquals((short) (StructNlMsgHdr.NLM_F_REPLACE | StructNlMsgHdr.NLM_F_REQUEST
- | StructNlMsgHdr.NLM_F_ACK), hdr.nlmsg_flags);
- assertEquals(1, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
- assertNotNull(nfmsgHdr);
- assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
- assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
- assertEquals((short) 0, nfmsgHdr.res_id);
-
- assertEquals(InetAddress.parseNumericAddress("100.96.167.146"),
- conntrackMessage.tupleOrig.srcIp);
- assertEquals(InetAddress.parseNumericAddress("216.58.197.10"),
- conntrackMessage.tupleOrig.dstIp);
- assertEquals((byte) OsConstants.IPPROTO_UDP, conntrackMessage.tupleOrig.protoNum);
- assertEquals((short) 37069, conntrackMessage.tupleOrig.srcPort);
- assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
-
- assertNull(conntrackMessage.tupleReply);
-
- assertEquals(0 /* absent */, conntrackMessage.status);
- assertEquals(180, conntrackMessage.timeoutSec);
- }
-
- public static final String CT_V4NEW_TCP_HEX =
- // CHECKSTYLE:OFF IndentationCheck
- // struct nlmsghdr
- "8C000000" + // length = 140
- "0001" + // type = NFNL_SUBSYS_CTNETLINK (1) << 8 | IPCTNL_MSG_CT_NEW (0)
- "0006" + // flags = NLM_F_CREATE (1 << 10) | NLM_F_EXCL (1 << 9)
- "00000000" + // seqno = 0
- "00000000" + // pid = 0
- // struct nfgenmsg
- "02" + // nfgen_family = AF_INET
- "00" + // version = NFNETLINK_V0
- "1234" + // res_id = 0x1234 (big endian)
- // struct nlattr
- "3400" + // nla_len = 52
- "0180" + // nla_type = nested CTA_TUPLE_ORIG
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 C0A8500C" + // nla_type=CTA_IP_V4_SRC, ip=192.168.80.12
- "0800 0200 8C700874" + // nla_type=CTA_IP_V4_DST, ip=140.112.8.116
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6)
- "0600 0200 F3F1 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=62449 (big endian)
- "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
- // struct nlattr
- "3400" + // nla_len = 52
- "0280" + // nla_type = nested CTA_TUPLE_REPLY
- // struct nlattr
- "1400" + // nla_len = 20
- "0180" + // nla_type = nested CTA_TUPLE_IP
- "0800 0100 8C700874" + // nla_type=CTA_IP_V4_SRC, ip=140.112.8.116
- "0800 0200 6451B301" + // nla_type=CTA_IP_V4_DST, ip=100.81.179.1
- // struct nlattr
- "1C00" + // nla_len = 28
- "0280" + // nla_type = nested CTA_TUPLE_PROTO
- "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=IPPROTO_TCP (6)
- "0600 0200 01BB 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=443 (big endian)
- "0600 0300 F3F1 0000" + // nla_type=CTA_PROTO_DST_PORT, port=62449 (big endian)
- // struct nlattr
- "0800" + // nla_len = 8
- "0300" + // nla_type = CTA_STATUS
- "00000198" + // nla_value = 0b110011000 (big endian)
- // IPS_CONFIRMED (1 << 3) | IPS_SRC_NAT (1 << 4) |
- // IPS_SRC_NAT_DONE (1 << 7) | IPS_DST_NAT_DONE (1 << 8)
- // struct nlattr
- "0800" + // nla_len = 8
- "0700" + // nla_type = CTA_TIMEOUT
- "00000078"; // nla_value = 120 (big endian)
- // CHECKSTYLE:ON IndentationCheck
- public static final byte[] CT_V4NEW_TCP_BYTES =
- HexEncoding.decode(CT_V4NEW_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
-
- @Test
- public void testParseCtNew() {
- assumeTrue(USING_LE);
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_V4NEW_TCP_BYTES);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
- assertNotNull(msg);
- assertTrue(msg instanceof ConntrackMessage);
- final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
-
- final StructNlMsgHdr hdr = conntrackMessage.getHeader();
- assertNotNull(hdr);
- assertEquals(140, hdr.nlmsg_len);
- assertEquals(makeCtType(IPCTNL_MSG_CT_NEW), hdr.nlmsg_type);
- assertEquals((short) (StructNlMsgHdr.NLM_F_CREATE | StructNlMsgHdr.NLM_F_EXCL),
- hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNfGenMsg nfmsgHdr = conntrackMessage.nfGenMsg;
- assertNotNull(nfmsgHdr);
- assertEquals((byte) OsConstants.AF_INET, nfmsgHdr.nfgen_family);
- assertEquals((byte) StructNfGenMsg.NFNETLINK_V0, nfmsgHdr.version);
- assertEquals((short) 0x1234, nfmsgHdr.res_id);
-
- assertEquals(InetAddress.parseNumericAddress("192.168.80.12"),
- conntrackMessage.tupleOrig.srcIp);
- assertEquals(InetAddress.parseNumericAddress("140.112.8.116"),
- conntrackMessage.tupleOrig.dstIp);
- assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleOrig.protoNum);
- assertEquals((short) 62449, conntrackMessage.tupleOrig.srcPort);
- assertEquals((short) 443, conntrackMessage.tupleOrig.dstPort);
-
- assertEquals(InetAddress.parseNumericAddress("140.112.8.116"),
- conntrackMessage.tupleReply.srcIp);
- assertEquals(InetAddress.parseNumericAddress("100.81.179.1"),
- conntrackMessage.tupleReply.dstIp);
- assertEquals((byte) OsConstants.IPPROTO_TCP, conntrackMessage.tupleReply.protoNum);
- assertEquals((short) 443, conntrackMessage.tupleReply.srcPort);
- assertEquals((short) 62449, conntrackMessage.tupleReply.dstPort);
-
- assertEquals(0x198, conntrackMessage.status);
- assertEquals(120, conntrackMessage.timeoutSec);
- }
-
- @Test
- public void testParseTruncation() {
- assumeTrue(USING_LE);
-
- // Expect no crash while parsing the truncated message which has been truncated to every
- // length between 0 and its full length - 1.
- for (int len = 0; len < CT_V4NEW_TCP_BYTES.length; len++) {
- final byte[] truncated = Arrays.copyOfRange(CT_V4NEW_TCP_BYTES, 0, len);
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(truncated);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
- OsConstants.NETLINK_NETFILTER);
- }
- }
-
- @Test
- public void testParseTruncationWithInvalidByte() {
- assumeTrue(USING_LE);
-
- // Expect no crash while parsing the message which is truncated by invalid bytes. The
- // message has been truncated to every length between 0 and its full length - 1.
- for (byte invalid : new byte[]{(byte) 0x00, (byte) 0xff}) {
- for (int len = 0; len < CT_V4NEW_TCP_BYTES.length; len++) {
- final byte[] truncated = new byte[CT_V4NEW_TCP_BYTES.length];
- Arrays.fill(truncated, (byte) invalid);
- System.arraycopy(CT_V4NEW_TCP_BYTES, 0, truncated, 0, len);
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(truncated);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
- OsConstants.NETLINK_NETFILTER);
- }
- }
- }
-
- // Malformed conntrack messages.
- public static final String CT_MALFORMED_HEX =
- // CHECKSTYLE:OFF IndentationCheck
- // <-- nlmsghr -->|<-nfgenmsg->|<-- CTA_TUPLE_ORIG -->|
- // CTA_TUPLE_ORIG has no nla_value.
- "18000000 0001 0006 00000000 00000000 02 00 0000 0400 0180"
- // nested CTA_TUPLE_IP has no nla_value.
- + "1C000000 0001 0006 00000000 00000000 02 00 0000 0800 0180 0400 0180"
- // nested CTA_IP_V4_SRC has no nla_value.
- + "20000000 0001 0006 00000000 00000000 02 00 0000 0C00 0180 0800 0180 0400 0100"
- // nested CTA_TUPLE_PROTO has no nla_value.
- // <-- nlmsghr -->|<-nfgenmsg->|<-- CTA_TUPLE_ORIG
- + "30000000 0001 0006 00000000 00000000 02 00 0000 1C00 0180 1400 0180 0800 0100"
- // -->|
- + "C0A8500C 0800 0200 8C700874 0400 0280";
- // CHECKSTYLE:ON IndentationCheck
- public static final byte[] CT_MALFORMED_BYTES =
- HexEncoding.decode(CT_MALFORMED_HEX.replaceAll(" ", "").toCharArray(), false);
-
- @Test
- public void testParseMalformation() {
- assumeTrue(USING_LE);
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_MALFORMED_BYTES);
- byteBuffer.order(ByteOrder.nativeOrder());
-
- // Expect no crash while parsing the malformed message.
- int messageCount = 0;
- while (byteBuffer.remaining() > 0) {
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer,
- OsConstants.NETLINK_NETFILTER);
- messageCount++;
- }
- assertEquals(4, messageCount);
- }
-
- @Test
- public void testToString() {
- assumeTrue(USING_LE);
-
- final ByteBuffer byteBuffer = ByteBuffer.wrap(CT_V4NEW_TCP_BYTES);
- byteBuffer.order(ByteOrder.nativeOrder());
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, OsConstants.NETLINK_NETFILTER);
- assertNotNull(msg);
- assertTrue(msg instanceof ConntrackMessage);
- final ConntrackMessage conntrackMessage = (ConntrackMessage) msg;
-
- // Bug: "nlmsg_flags{1536(NLM_F_MATCH))" is not correct because StructNlMsgHdr
- // #stringForNlMsgFlags can't convert all flags (ex: NLM_F_CREATE) and can't distinguish
- // the flags which have the same value (ex: NLM_F_MATCH <0x200> and NLM_F_EXCL <0x200>).
- // The flags output string should be "NLM_F_CREATE|NLM_F_EXCL" in this case.
- // TODO: correct the flag converted string once #stringForNlMsgFlags does.
- final String expected = ""
- + "ConntrackMessage{"
- + "nlmsghdr{StructNlMsgHdr{ nlmsg_len{140}, nlmsg_type{256(IPCTNL_MSG_CT_NEW)}, "
- + "nlmsg_flags{1536(NLM_F_MATCH))}, nlmsg_seq{0}, nlmsg_pid{0} }}, "
- + "nfgenmsg{NfGenMsg{ nfgen_family{AF_INET}, version{0}, res_id{4660} }}, "
- + "tuple_orig{Tuple{IPPROTO_TCP: 192.168.80.12:62449 -> 140.112.8.116:443}}, "
- + "tuple_reply{Tuple{IPPROTO_TCP: 140.112.8.116:443 -> 100.81.179.1:62449}}, "
- + "status{408(IPS_CONFIRMED|IPS_SRC_NAT|IPS_SRC_NAT_DONE|IPS_DST_NAT_DONE)}, "
- + "timeout_sec{120}}";
- assertEquals(expected, conntrackMessage.toString());
- }
-}
diff --git a/tests/unit/src/android/net/netlink/InetDiagSocketTest.java b/tests/unit/src/android/net/netlink/InetDiagSocketTest.java
deleted file mode 100644
index fcc85a2..0000000
--- a/tests/unit/src/android/net/netlink/InetDiagSocketTest.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2018 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.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_TCP;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class InetDiagSocketTest {
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "02" + // family = AF_INET
- "11" + // protcol = IPPROTO_UDP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "a5de" + // idiag_sport = 42462
- "b971" + // idiag_dport = 47473
- "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
- "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
- private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2UdpInet4() throws Exception {
- InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"),
- 42462);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET,
- (short) (NLM_F_REQUEST | NLM_F_DUMP));
- assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "0a" + // family = AF_INET6
- "06" + // protcol = IPPROTO_TCP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "a5de" + // idiag_sport = 42462
- "b971" + // idiag_dport = 47473
- "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
- "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2TcpInet6() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
- NLM_F_REQUEST);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
- private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "02" + // family = AF_INET
- "06" + // protcol = IPPROTO_TCP
- "02" + // idiag_ext = INET_DIAG_INFO
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "3039" + // idiag_sport = 12345
- "d431" + // idiag_dport = 54321
- "01020304000000000000000000000000" + // idiag_src = 1.2.3.4
- "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
- "00000000" + // idiag_if
- "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
-
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
- private static final int TCP_ALL_STATES = 0xffffffff;
- @Test
- public void testInetDiagReqV2TcpInetWithExt() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("1.2.3.4"), 12345);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
- 54321);
- byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
- NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
-
- local = new InetSocketAddress(
- InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
- remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
- 47473);
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
-
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request with no socket specified.
- private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
- // struct nlmsghdr
- "48000000" + // length = 72
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0100" + // flags = NLM_F_REQUEST
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct inet_diag_req_v2
- "0a" + // family = AF_INET6
- "06" + // protcol = IPPROTO_TCP
- "00" + // idiag_ext
- "00" + // pad
- "ffffffff" + // idiag_states
- // inet_diag_sockid
- "0000" + // idiag_sport
- "0000" + // idiag_dport
- "00000000000000000000000000000000" + // idiag_src
- "00000000000000000000000000000000" + // idiag_dst
- "00000000" + // idiag_if
- "0000000000000000"; // idiag_cookie
-
- private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
- HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
-
- @Test
- public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
- InetSocketAddress local = new InetSocketAddress(
- InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
- InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
- 54321);
- // Verify no socket specified if either local or remote socket address is null.
- byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- byte[] msg;
- try {
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
- NLM_F_REQUEST);
- fail("Both remote and local should be null, expected UnknownHostException");
- } catch (NullPointerException e) {
- }
-
- try {
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- fail("Both remote and local should be null, expected UnknownHostException");
- } catch (NullPointerException e) {
- }
-
- msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
- NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
- assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
- }
-
- // Hexadecimal representation of InetDiagReqV2 request.
- private static final String INET_DIAG_MSG_HEX =
- // struct nlmsghdr
- "58000000" + // length = 88
- "1400" + // type = SOCK_DIAG_BY_FAMILY
- "0200" + // flags = NLM_F_MULTI
- "00000000" + // seqno
- "f5220000" + // pid (0 == kernel)
- // struct inet_diag_msg
- "0a" + // family = AF_INET6
- "01" + // idiag_state
- "00" + // idiag_timer
- "00" + // idiag_retrans
- // inet_diag_sockid
- "a817" + // idiag_sport = 43031
- "960f" + // idiag_dport = 38415
- "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
- "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8
- "00000000" + // idiag_if
- "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE
- "00000000" + // idiag_expires
- "00000000" + // idiag_rqueue
- "00000000" + // idiag_wqueue
- "a3270000" + // idiag_uid
- "A57E1900"; // idiag_inode
- private static final byte[] INET_DIAG_MSG_BYTES =
- HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false);
-
- @Test
- public void testParseInetDiagResponse() throws Exception {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_INET_DIAG);
- assertNotNull(msg);
-
- assertTrue(msg instanceof InetDiagMessage);
- final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
- assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid);
-
- final StructNlMsgHdr hdr = inetDiagMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type);
- assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(8949, hdr.nlmsg_pid);
- }
-}
diff --git a/tests/unit/src/android/net/netlink/NduseroptMessageTest.java b/tests/unit/src/android/net/netlink/NduseroptMessageTest.java
deleted file mode 100644
index b070d61..0000000
--- a/tests/unit/src/android/net/netlink/NduseroptMessageTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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.netlink;
-
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.IpPrefix;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NduseroptMessageTest {
-
- private static final byte ICMP_TYPE_RA = (byte) 134;
-
- private static final int IFINDEX1 = 15715755;
- private static final int IFINDEX2 = 1431655765;
-
- // IPv6, 0 bytes of options, interface index 15715755, type 134 (RA), code 0, padding.
- private static final String HDR_EMPTY = "0a00" + "0000" + "abcdef00" + "8600000000000000";
-
- // IPv6, 16 bytes of options, interface index 1431655765, type 134 (RA), code 0, padding.
- private static final String HDR_16BYTE = "0a00" + "1000" + "55555555" + "8600000000000000";
-
- // IPv6, 32 bytes of options, interface index 1431655765, type 134 (RA), code 0, padding.
- private static final String HDR_32BYTE = "0a00" + "2000" + "55555555" + "8600000000000000";
-
- // PREF64 option, 2001:db8:3:4:5:6::/96, lifetime=10064
- private static final String OPT_PREF64 = "2602" + "2750" + "20010db80003000400050006";
-
- // Length 20, NDUSEROPT_SRCADDR, fe80:2:3:4:5:6:7:8
- private static final String NLA_SRCADDR = "1400" + "0100" + "fe800002000300040005000600070008";
-
- private static final InetAddress SADDR1 = parseNumericAddress("fe80:2:3:4:5:6:7:8%" + IFINDEX1);
- private static final InetAddress SADDR2 = parseNumericAddress("fe80:2:3:4:5:6:7:8%" + IFINDEX2);
-
- private static final String MSG_EMPTY = HDR_EMPTY + NLA_SRCADDR;
- private static final String MSG_PREF64 = HDR_16BYTE + OPT_PREF64 + NLA_SRCADDR;
-
- @Test
- public void testParsing() {
- NduseroptMessage msg = parseNduseroptMessage(toBuffer(MSG_EMPTY));
- assertMatches(AF_INET6, 0, IFINDEX1, ICMP_TYPE_RA, (byte) 0, SADDR1, msg);
- assertNull(msg.option);
-
- msg = parseNduseroptMessage(toBuffer(MSG_PREF64));
- assertMatches(AF_INET6, 16, IFINDEX2, ICMP_TYPE_RA, (byte) 0, SADDR2, msg);
- assertPref64Option("2001:db8:3:4:5:6::/96", msg.option);
- }
-
- @Test
- public void testParseWithinNetlinkMessage() throws Exception {
- // A NduseroptMessage inside a netlink message. Ensure that it parses the same way both by
- // parsing the netlink message via NetlinkMessage.parse() and by parsing the option itself
- // with NduseroptMessage.parse().
- final String hexBytes =
- "44000000440000000000000000000000" // len=68, RTM_NEWNDUSEROPT
- + "0A0010001E0000008600000000000000" // IPv6, opt_bytes=16, ifindex=30, RA
- + "260202580064FF9B0000000000000000" // pref64, prefix=64:ff9b::/96, 600
- + "14000100FE800000000000000250B6FFFEB7C499"; // srcaddr=fe80::250:b6ff:feb7:c499
-
- ByteBuffer buf = toBuffer(hexBytes);
- assertEquals(68, buf.limit());
- buf.order(ByteOrder.nativeOrder());
-
- NetlinkMessage nlMsg = NetlinkMessage.parse(buf, NETLINK_ROUTE);
- assertNotNull(nlMsg);
- assertTrue(nlMsg instanceof NduseroptMessage);
-
- NduseroptMessage msg = (NduseroptMessage) nlMsg;
- InetAddress srcaddr = InetAddress.getByName("fe80::250:b6ff:feb7:c499%30");
- assertMatches(AF_INET6, 16, 30, ICMP_TYPE_RA, (byte) 0, srcaddr, msg);
- assertPref64Option("64:ff9b::/96", msg.option);
-
- final String hexBytesWithoutHeader = hexBytes.substring(StructNlMsgHdr.STRUCT_SIZE * 2);
- ByteBuffer bufWithoutHeader = toBuffer(hexBytesWithoutHeader);
- assertEquals(52, bufWithoutHeader.limit());
- msg = parseNduseroptMessage(bufWithoutHeader);
- assertMatches(AF_INET6, 16, 30, ICMP_TYPE_RA, (byte) 0, srcaddr, msg);
- assertPref64Option("64:ff9b::/96", msg.option);
- }
-
- @Test
- public void testParseUnknownOptionWithinNetlinkMessage() throws Exception {
- final String hexBytes =
- "4C0000004400000000000000000000000"
- + "A0018001E0000008600000000000000"
- + "1903000000001770FD123456789000000000000000000001" // RDNSS option
- + "14000100FE800000000000000250B6FFFEB7C499";
-
- ByteBuffer buf = toBuffer(hexBytes);
- assertEquals(76, buf.limit());
- buf.order(ByteOrder.nativeOrder());
-
- NetlinkMessage nlMsg = NetlinkMessage.parse(buf, NETLINK_ROUTE);
- assertNotNull(nlMsg);
- assertTrue(nlMsg instanceof NduseroptMessage);
-
- NduseroptMessage msg = (NduseroptMessage) nlMsg;
- InetAddress srcaddr = InetAddress.getByName("fe80::250:b6ff:feb7:c499%30");
- assertMatches(AF_INET6, 24, 30, ICMP_TYPE_RA, (byte) 0, srcaddr, msg);
- assertEquals(NdOption.UNKNOWN, msg.option);
- }
-
- @Test
- public void testUnknownOption() {
- ByteBuffer buf = toBuffer(MSG_PREF64);
- // Replace the PREF64 option type (38) with an unknown option number.
- final int optionStart = NduseroptMessage.STRUCT_SIZE;
- assertEquals(38, buf.get(optionStart));
- buf.put(optionStart, (byte) 42);
-
- NduseroptMessage msg = parseNduseroptMessage(buf);
- assertMatches(AF_INET6, 16, IFINDEX2, ICMP_TYPE_RA, (byte) 0, SADDR2, msg);
- assertEquals(NdOption.UNKNOWN, msg.option);
-
- buf.flip();
- assertEquals(42, buf.get(optionStart));
- buf.put(optionStart, (byte) 38);
-
- msg = parseNduseroptMessage(buf);
- assertMatches(AF_INET6, 16, IFINDEX2, ICMP_TYPE_RA, (byte) 0, SADDR2, msg);
- assertPref64Option("2001:db8:3:4:5:6::/96", msg.option);
- }
-
- @Test
- public void testZeroLengthOption() {
- // Make sure an unknown option with a 0-byte length is ignored and parsing continues with
- // the address, which comes after it.
- final String hexString = HDR_16BYTE + "00000000000000000000000000000000" + NLA_SRCADDR;
- ByteBuffer buf = toBuffer(hexString);
- assertEquals(52, buf.limit());
- NduseroptMessage msg = parseNduseroptMessage(buf);
- assertMatches(AF_INET6, 16, IFINDEX2, ICMP_TYPE_RA, (byte) 0, SADDR2, msg);
- assertNull(msg.option);
- }
-
- @Test
- public void testTooLongOption() {
- // Make sure that if an option's length is too long, it's ignored and parsing continues with
- // the address, which comes after it.
- final String hexString = HDR_16BYTE + "26030000000000000000000000000000" + NLA_SRCADDR;
- ByteBuffer buf = toBuffer(hexString);
- assertEquals(52, buf.limit());
- NduseroptMessage msg = parseNduseroptMessage(buf);
- assertMatches(AF_INET6, 16, IFINDEX2, ICMP_TYPE_RA, (byte) 0, SADDR2, msg);
- assertNull(msg.option);
- }
-
- @Test
- public void testOptionsTooLong() {
- // Header claims 32 bytes of options. Buffer ends before options end.
- String hexString = HDR_32BYTE + OPT_PREF64;
- ByteBuffer buf = toBuffer(hexString);
- assertEquals(32, buf.limit());
- assertNull(NduseroptMessage.parse(toBuffer(hexString), NETLINK_ROUTE));
-
- // Header claims 32 bytes of options. Buffer ends at end of options with no source address.
- hexString = HDR_32BYTE + OPT_PREF64 + OPT_PREF64;
- buf = toBuffer(hexString);
- assertEquals(48, buf.limit());
- assertNull(NduseroptMessage.parse(toBuffer(hexString), NETLINK_ROUTE));
- }
-
- @Test
- public void testTruncation() {
- final int optLen = MSG_PREF64.length() / 2; // 1 byte = 2 hex chars
- for (int len = 0; len < optLen; len++) {
- ByteBuffer buf = toBuffer(MSG_PREF64.substring(0, len * 2));
- NduseroptMessage msg = parseNduseroptMessage(buf);
- if (len < optLen) {
- assertNull(msg);
- } else {
- assertNotNull(msg);
- assertPref64Option("2001:db8:3:4:5:6::/96", msg.option);
- }
- }
- }
-
- @Test
- public void testToString() {
- NduseroptMessage msg = parseNduseroptMessage(toBuffer(MSG_PREF64));
- assertNotNull(msg);
- assertEquals("Nduseroptmsg(10, 16, 1431655765, 134, 0, fe80:2:3:4:5:6:7:8%1431655765)",
- msg.toString());
- }
-
- // Convenience method to parse a NduseroptMessage that's not part of a netlink message.
- private NduseroptMessage parseNduseroptMessage(ByteBuffer buf) {
- return NduseroptMessage.parse(null, buf);
- }
-
- private ByteBuffer toBuffer(String hexString) {
- return ByteBuffer.wrap(HexEncoding.decode(hexString));
- }
-
- private void assertMatches(int family, int optsLen, int ifindex, byte icmpType,
- byte icmpCode, InetAddress srcaddr, NduseroptMessage msg) {
- assertNotNull(msg);
- assertEquals(family, msg.family);
- assertEquals(ifindex, msg.ifindex);
- assertEquals(optsLen, msg.opts_len);
- assertEquals(icmpType, msg.icmp_type);
- assertEquals(icmpCode, msg.icmp_code);
- assertEquals(srcaddr, msg.srcaddr);
- }
-
- private void assertPref64Option(String prefix, NdOption opt) {
- assertNotNull(opt);
- assertTrue(opt instanceof StructNdOptPref64);
- StructNdOptPref64 pref64Opt = (StructNdOptPref64) opt;
- assertEquals(new IpPrefix(prefix), pref64Opt.prefix);
- }
-}
diff --git a/tests/unit/src/android/net/netlink/NetlinkConstantsTest.java b/tests/unit/src/android/net/netlink/NetlinkConstantsTest.java
deleted file mode 100644
index 131feeb..0000000
--- a/tests/unit/src/android/net/netlink/NetlinkConstantsTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.netlink;
-
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_DELETE;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_CTRZERO;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_DYING;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_STATS_CPU;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_GET_UNCONFIRMED;
-import static android.net.netlink.NetlinkConstants.IPCTNL_MSG_CT_NEW;
-import static android.net.netlink.NetlinkConstants.NFNL_SUBSYS_CTNETLINK;
-import static android.net.netlink.NetlinkConstants.NLMSG_DONE;
-import static android.net.netlink.NetlinkConstants.NLMSG_ERROR;
-import static android.net.netlink.NetlinkConstants.NLMSG_NOOP;
-import static android.net.netlink.NetlinkConstants.NLMSG_OVERRUN;
-import static android.net.netlink.NetlinkConstants.RTM_DELADDR;
-import static android.net.netlink.NetlinkConstants.RTM_DELLINK;
-import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
-import static android.net.netlink.NetlinkConstants.RTM_DELROUTE;
-import static android.net.netlink.NetlinkConstants.RTM_DELRULE;
-import static android.net.netlink.NetlinkConstants.RTM_GETADDR;
-import static android.net.netlink.NetlinkConstants.RTM_GETLINK;
-import static android.net.netlink.NetlinkConstants.RTM_GETNEIGH;
-import static android.net.netlink.NetlinkConstants.RTM_GETROUTE;
-import static android.net.netlink.NetlinkConstants.RTM_GETRULE;
-import static android.net.netlink.NetlinkConstants.RTM_NEWADDR;
-import static android.net.netlink.NetlinkConstants.RTM_NEWLINK;
-import static android.net.netlink.NetlinkConstants.RTM_NEWNDUSEROPT;
-import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
-import static android.net.netlink.NetlinkConstants.RTM_NEWROUTE;
-import static android.net.netlink.NetlinkConstants.RTM_NEWRULE;
-import static android.net.netlink.NetlinkConstants.RTM_SETLINK;
-import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
-import static android.net.netlink.NetlinkConstants.stringForNlMsgType;
-import static android.system.OsConstants.NETLINK_INET_DIAG;
-import static android.system.OsConstants.NETLINK_NETFILTER;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkConstantsTest {
- private static final short UNKNOWN_FAMILY = 1234;
-
- private short makeCtType(short msgType) {
- return (short) (NFNL_SUBSYS_CTNETLINK << 8 | (byte) msgType);
- }
-
- @Test
- public void testStringForNlMsgType() {
- assertEquals("RTM_NEWLINK", stringForNlMsgType(RTM_NEWLINK, NETLINK_ROUTE));
- assertEquals("RTM_DELLINK", stringForNlMsgType(RTM_DELLINK, NETLINK_ROUTE));
- assertEquals("RTM_GETLINK", stringForNlMsgType(RTM_GETLINK, NETLINK_ROUTE));
- assertEquals("RTM_SETLINK", stringForNlMsgType(RTM_SETLINK, NETLINK_ROUTE));
- assertEquals("RTM_NEWADDR", stringForNlMsgType(RTM_NEWADDR, NETLINK_ROUTE));
- assertEquals("RTM_DELADDR", stringForNlMsgType(RTM_DELADDR, NETLINK_ROUTE));
- assertEquals("RTM_GETADDR", stringForNlMsgType(RTM_GETADDR, NETLINK_ROUTE));
- assertEquals("RTM_NEWROUTE", stringForNlMsgType(RTM_NEWROUTE, NETLINK_ROUTE));
- assertEquals("RTM_DELROUTE", stringForNlMsgType(RTM_DELROUTE, NETLINK_ROUTE));
- assertEquals("RTM_GETROUTE", stringForNlMsgType(RTM_GETROUTE, NETLINK_ROUTE));
- assertEquals("RTM_NEWNEIGH", stringForNlMsgType(RTM_NEWNEIGH, NETLINK_ROUTE));
- assertEquals("RTM_DELNEIGH", stringForNlMsgType(RTM_DELNEIGH, NETLINK_ROUTE));
- assertEquals("RTM_GETNEIGH", stringForNlMsgType(RTM_GETNEIGH, NETLINK_ROUTE));
- assertEquals("RTM_NEWRULE", stringForNlMsgType(RTM_NEWRULE, NETLINK_ROUTE));
- assertEquals("RTM_DELRULE", stringForNlMsgType(RTM_DELRULE, NETLINK_ROUTE));
- assertEquals("RTM_GETRULE", stringForNlMsgType(RTM_GETRULE, NETLINK_ROUTE));
- assertEquals("RTM_NEWNDUSEROPT", stringForNlMsgType(RTM_NEWNDUSEROPT, NETLINK_ROUTE));
-
- assertEquals("SOCK_DIAG_BY_FAMILY",
- stringForNlMsgType(SOCK_DIAG_BY_FAMILY, NETLINK_INET_DIAG));
-
- assertEquals("IPCTNL_MSG_CT_NEW",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_DELETE",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_DELETE), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET_CTRZERO",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_CTRZERO), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET_STATS_CPU",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS_CPU), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET_STATS",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_STATS), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET_DYING",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_DYING), NETLINK_NETFILTER));
- assertEquals("IPCTNL_MSG_CT_GET_UNCONFIRMED",
- stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_GET_UNCONFIRMED), NETLINK_NETFILTER));
- }
-
- @Test
- public void testStringForNlMsgType_ControlMessage() {
- for (int family : new int[]{NETLINK_ROUTE, NETLINK_INET_DIAG, NETLINK_NETFILTER}) {
- assertEquals("NLMSG_NOOP", stringForNlMsgType(NLMSG_NOOP, family));
- assertEquals("NLMSG_ERROR", stringForNlMsgType(NLMSG_ERROR, family));
- assertEquals("NLMSG_DONE", stringForNlMsgType(NLMSG_DONE, family));
- assertEquals("NLMSG_OVERRUN", stringForNlMsgType(NLMSG_OVERRUN, family));
- }
- }
-
- @Test
- public void testStringForNlMsgType_UnknownFamily() {
- assertTrue(stringForNlMsgType(RTM_NEWLINK, UNKNOWN_FAMILY).startsWith("unknown"));
- assertTrue(stringForNlMsgType(SOCK_DIAG_BY_FAMILY, UNKNOWN_FAMILY).startsWith("unknown"));
- assertTrue(stringForNlMsgType(makeCtType(IPCTNL_MSG_CT_NEW), UNKNOWN_FAMILY)
- .startsWith("unknown"));
- }
-}
diff --git a/tests/unit/src/android/net/netlink/NetlinkErrorMessageTest.java b/tests/unit/src/android/net/netlink/NetlinkErrorMessageTest.java
deleted file mode 100644
index 345622f..0000000
--- a/tests/unit/src/android/net/netlink/NetlinkErrorMessageTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2015 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.netlink;
-
-import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
-import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkErrorMessage;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.StructNlMsgErr;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkErrorMessageTest {
- private final String TAG = "NetlinkErrorMessageTest";
-
- // Hexadecimal representation of packet capture.
- public static final String NLM_ERROR_OK_HEX =
- // struct nlmsghdr
- "24000000" + // length = 36
- "0200" + // type = 2 (NLMSG_ERROR)
- "0000" + // flags
- "26350000" + // seqno
- "64100000" + // pid = userspace process
- // error integer
- "00000000" + // "errno" (0 == OK)
- // struct nlmsghdr
- "30000000" + // length (48) of original request
- "1C00" + // type = 28 (RTM_NEWNEIGH)
- "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
- "26350000" + // seqno
- "00000000"; // pid = kernel
- public static final byte[] NLM_ERROR_OK =
- HexEncoding.decode(NLM_ERROR_OK_HEX.toCharArray(), false);
-
- @Test
- public void testParseNlmErrorOk() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(NLM_ERROR_OK);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE);
- assertNotNull(msg);
- assertTrue(msg instanceof NetlinkErrorMessage);
- final NetlinkErrorMessage errorMsg = (NetlinkErrorMessage) msg;
-
- final StructNlMsgHdr hdr = errorMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(36, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.NLMSG_ERROR, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(13606, hdr.nlmsg_seq);
- assertEquals(4196, hdr.nlmsg_pid);
-
- final StructNlMsgErr err = errorMsg.getNlMsgError();
- assertNotNull(err);
- assertEquals(0, err.error);
- assertNotNull(err.msg);
- assertEquals(48, err.msg.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, err.msg.nlmsg_type);
- assertEquals((NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE), err.msg.nlmsg_flags);
- assertEquals(13606, err.msg.nlmsg_seq);
- assertEquals(0, err.msg.nlmsg_pid);
- }
-}
diff --git a/tests/unit/src/android/net/netlink/NetlinkSocketTest.java b/tests/unit/src/android/net/netlink/NetlinkSocketTest.java
deleted file mode 100644
index 5716803..0000000
--- a/tests/unit/src/android/net/netlink/NetlinkSocketTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2015 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.netlink;
-
-import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.netlink.NetlinkSocket;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.NetlinkSocketAddress;
-import android.system.Os;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.io.IoUtils;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileDescriptor;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class NetlinkSocketTest {
- private final String TAG = "NetlinkSocketTest";
-
- @Test
- public void testBasicWorkingGetNeighborsQuery() throws Exception {
- final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_ROUTE);
- assertNotNull(fd);
-
- NetlinkSocket.connectToKernel(fd);
-
- final NetlinkSocketAddress localAddr = (NetlinkSocketAddress) Os.getsockname(fd);
- assertNotNull(localAddr);
- assertEquals(0, localAddr.getGroupsMask());
- assertTrue(0 != localAddr.getPortId());
-
- final int TEST_SEQNO = 5;
- final byte[] req = RtNetlinkNeighborMessage.newGetNeighborsRequest(TEST_SEQNO);
- assertNotNull(req);
-
- final long TIMEOUT = 500;
- assertEquals(req.length, NetlinkSocket.sendMessage(fd, req, 0, req.length, TIMEOUT));
-
- int neighMessageCount = 0;
- int doneMessageCount = 0;
-
- while (doneMessageCount == 0) {
- ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT);
- assertNotNull(response);
- assertTrue(StructNlMsgHdr.STRUCT_SIZE <= response.limit());
- assertEquals(0, response.position());
- assertEquals(ByteOrder.nativeOrder(), response.order());
-
- // Verify the messages at least appears minimally reasonable.
- while (response.remaining() > 0) {
- final NetlinkMessage msg = NetlinkMessage.parse(response, NETLINK_ROUTE);
- assertNotNull(msg);
- final StructNlMsgHdr hdr = msg.getHeader();
- assertNotNull(hdr);
-
- if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
- doneMessageCount++;
- continue;
- }
-
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- assertTrue((hdr.nlmsg_flags & StructNlMsgHdr.NLM_F_MULTI) != 0);
- assertEquals(TEST_SEQNO, hdr.nlmsg_seq);
- assertEquals(localAddr.getPortId(), hdr.nlmsg_pid);
-
- neighMessageCount++;
- }
- }
-
- assertEquals(1, doneMessageCount);
- // TODO: make sure this test passes sanely in airplane mode.
- assertTrue(neighMessageCount > 0);
-
- IoUtils.closeQuietly(fd);
- }
-}
diff --git a/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt
deleted file mode 100644
index 3b485eb..0000000
--- a/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-@file:JvmName("NetlinkTestUtils")
-
-package android.net.netlink
-
-import android.net.netlink.NetlinkConstants.RTM_DELNEIGH
-import android.net.netlink.NetlinkConstants.RTM_NEWNEIGH
-import libcore.util.HexEncoding
-import libcore.util.HexEncoding.encodeToString
-import java.net.Inet6Address
-import java.net.InetAddress
-
-/**
- * Make a RTM_NEWNEIGH netlink message.
- */
-fun makeNewNeighMessage(
- neighAddr: InetAddress,
- nudState: Short
-) = makeNeighborMessage(
- neighAddr = neighAddr,
- type = RTM_NEWNEIGH,
- nudState = nudState
-)
-
-/**
- * Make a RTM_DELNEIGH netlink message.
- */
-fun makeDelNeighMessage(
- neighAddr: InetAddress,
- nudState: Short
-) = makeNeighborMessage(
- neighAddr = neighAddr,
- type = RTM_DELNEIGH,
- nudState = nudState
-)
-
-private fun makeNeighborMessage(
- neighAddr: InetAddress,
- type: Short,
- nudState: Short
-) = HexEncoding.decode(
- /* ktlint-disable indent */
- // -- struct nlmsghdr --
- // length = 88 or 76:
- (if (neighAddr is Inet6Address) "58000000" else "4c000000") +
- type.toLEHex() + // type
- "0000" + // flags
- "00000000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct ndmsg
- // family (AF_INET6 or AF_INET)
- (if (neighAddr is Inet6Address) "0a" else "02") +
- "00" + // pad1
- "0000" + // pad2
- "15000000" + // interface index (21 == wlan0, on test device)
- nudState.toLEHex() + // NUD state
- "00" + // flags
- "01" + // type
- // -- struct nlattr: NDA_DST --
- // length = 20 or 8:
- (if (neighAddr is Inet6Address) "1400" else "0800") +
- "0100" + // type (1 == NDA_DST, for neighbor messages)
- // IP address:
- encodeToString(neighAddr.address) +
- // -- struct nlattr: NDA_LLADDR --
- "0a00" + // length = 10
- "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
- "00005e000164" + // MAC Address (== 00:00:5e:00:01:64)
- "0000" + // padding, for 4 byte alignment
- // -- struct nlattr: NDA_PROBES --
- "0800" + // length = 8
- "0400" + // type (4 == NDA_PROBES, for neighbor messages)
- "01000000" + // number of probes
- // -- struct nlattr: NDA_CACHEINFO --
- "1400" + // length = 20
- "0300" + // type (3 == NDA_CACHEINFO, for neighbor messages)
- "05190000" + // ndm_used, as "clock ticks ago"
- "05190000" + // ndm_confirmed, as "clock ticks ago"
- "190d0000" + // ndm_updated, as "clock ticks ago"
- "00000000", // ndm_refcnt
- false /* allowSingleChar */)
- /* ktlint-enable indent */
-
-/**
- * Convert a [Short] to a little-endian hex string.
- */
-private fun Short.toLEHex() = String.format("%04x", java.lang.Short.reverseBytes(this))
diff --git a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
deleted file mode 100644
index a1f1d44..0000000
--- a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ /dev/null
@@ -1,211 +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.netlink;
-
-import static android.net.netlink.NetlinkTestUtils.makeDelNeighMessage;
-import static android.net.netlink.NetlinkTestUtils.makeNewNeighMessage;
-import static android.net.netlink.StructNdMsg.NUD_STALE;
-import static android.system.OsConstants.NETLINK_ROUTE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.InetAddresses;
-import android.net.netlink.NetlinkConstants;
-import android.net.netlink.NetlinkMessage;
-import android.net.netlink.RtNetlinkNeighborMessage;
-import android.net.netlink.StructNdMsg;
-import android.net.netlink.StructNlMsgHdr;
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RtNetlinkNeighborMessageTest {
- private final String TAG = "RtNetlinkNeighborMessageTest";
-
- public static final byte[] RTM_DELNEIGH = makeDelNeighMessage(
- InetAddresses.parseNumericAddress("192.168.159.254"), NUD_STALE);
-
- public static final byte[] RTM_NEWNEIGH = makeNewNeighMessage(
- InetAddresses.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), NUD_STALE);
-
- // An example of the full response from an RTM_GETNEIGH query.
- private static final String RTM_GETNEIGH_RESPONSE_HEX =
- // <-- struct nlmsghr -->|<-- struct ndmsg -->|<-- struct nlattr: NDA_DST -->|<-- NDA_LLADDR -->|<-- NDA_PROBES -->|<-- NDA_CACHEINFO -->|
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000001 0a00 0200 333300000001 0000 0800 0400 00000000 1400 0300 a2280000 32110000 32110000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff000001 0a00 0200 3333ff000001 0000 0800 0400 00000000 1400 0300 0d280000 9d100000 9d100000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0400 80 01 1400 0100 20010db800040ca00000000000000001 0a00 0200 84c9b26aed4b 0000 0800 0400 04000000 1400 0300 90100000 90100000 90080000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff47da19 0a00 0200 3333ff47da19 0000 0800 0400 00000000 1400 0300 a1280000 31110000 31110000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 912a0000 21130000 21130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 922a0000 22130000 22130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ff5c2a83 0a00 0200 3333ff5c2a83 0000 0800 0400 00000000 1400 0300 391c0000 c9040000 c9040000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 01000000 4000 00 02 1400 0100 00000000000000000000000000000000 0a00 0200 000000000000 0000 0800 0400 00000000 1400 0300 cd180200 5d010200 5d010200 08000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 352a0000 c5120000 c5120000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff020000000000000000000000000016 0a00 0200 333300000016 0000 0800 0400 00000000 1400 0300 982a0000 28130000 28130000 00000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 0800 80 01 1400 0100 fe8000000000000086c9b2fffe6aed4b 0a00 0200 84c9b26aed4b 0000 0800 0400 00000000 1400 0300 23000000 24000000 57000000 13000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 15000000 4000 00 05 1400 0100 ff0200000000000000000001ffeace3b 0a00 0200 3333ffeace3b 0000 0800 0400 00000000 1400 0300 992a0000 29130000 29130000 01000000" +
- "58000000 1c00 0200 00000000 3e2b0000 0a 00 0000 14000000 4000 00 05 1400 0100 ff020000000000000000000000000002 0a00 0200 333300000002 0000 0800 0400 00000000 1400 0300 2e2a0000 be120000 be120000 00000000" +
- "44000000 1c00 0200 00000000 3e2b0000 02 00 0000 18000000 4000 00 03 0800 0100 00000000 0400 0200 0800 0400 00000000 1400 0300 75280000 05110000 05110000 22000000";
- public static final byte[] RTM_GETNEIGH_RESPONSE =
- HexEncoding.decode(RTM_GETNEIGH_RESPONSE_HEX.replaceAll(" ", "").toCharArray(), false);
-
- @Test
- public void testParseRtmDelNeigh() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_DELNEIGH);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(76, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_DELNEIGH, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
- assertNotNull(ndmsgHdr);
- assertEquals((byte) OsConstants.AF_INET, ndmsgHdr.ndm_family);
- assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(NUD_STALE, ndmsgHdr.ndm_state);
- final InetAddress destination = neighMsg.getDestination();
- assertNotNull(destination);
- assertEquals(InetAddress.parseNumericAddress("192.168.159.254"), destination);
- }
-
- @Test
- public void testParseRtmNewNeigh() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_NEWNEIGH);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(88, hdr.nlmsg_len);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertEquals(0, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(0, hdr.nlmsg_pid);
-
- final StructNdMsg ndmsgHdr = neighMsg.getNdHeader();
- assertNotNull(ndmsgHdr);
- assertEquals((byte) OsConstants.AF_INET6, ndmsgHdr.ndm_family);
- assertEquals(21, ndmsgHdr.ndm_ifindex);
- assertEquals(NUD_STALE, ndmsgHdr.ndm_state);
- final InetAddress destination = neighMsg.getDestination();
- assertNotNull(destination);
- assertEquals(InetAddress.parseNumericAddress("fe80::86c9:b2ff:fe6a:ed4b"), destination);
- }
-
- @Test
- public void testParseRtmGetNeighResponse() {
- final ByteBuffer byteBuffer = ByteBuffer.wrap(RTM_GETNEIGH_RESPONSE);
- byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing.
-
- int messageCount = 0;
- while (byteBuffer.remaining() > 0) {
- final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE);
- assertNotNull(msg);
- assertTrue(msg instanceof RtNetlinkNeighborMessage);
- final RtNetlinkNeighborMessage neighMsg = (RtNetlinkNeighborMessage) msg;
-
- final StructNlMsgHdr hdr = neighMsg.getHeader();
- assertNotNull(hdr);
- assertEquals(NetlinkConstants.RTM_NEWNEIGH, hdr.nlmsg_type);
- assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
- assertEquals(0, hdr.nlmsg_seq);
- assertEquals(11070, hdr.nlmsg_pid);
-
- final int probes = neighMsg.getProbes();
- assertTrue("Unexpected number of probes. Got " + probes + ", max=5",
- probes < 5);
- final int ndm_refcnt = neighMsg.getCacheInfo().ndm_refcnt;
- assertTrue("nda_cacheinfo has unexpectedly high ndm_refcnt: " + ndm_refcnt,
- ndm_refcnt < 0x100);
-
- messageCount++;
- }
- // TODO: add more detailed spot checks.
- assertEquals(14, messageCount);
- }
-
- @Test
- public void testCreateRtmNewNeighMessage() {
- final int seqNo = 2635;
- final int ifIndex = 14;
- final byte[] llAddr =
- new byte[] { (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6 };
-
- // Hexadecimal representation of our created packet.
- final String expectedNewNeighHex =
- // struct nlmsghdr
- "30000000" + // length = 48
- "1c00" + // type = 28 (RTM_NEWNEIGH)
- "0501" + // flags (NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE)
- "4b0a0000" + // seqno
- "00000000" + // pid (0 == kernel)
- // struct ndmsg
- "02" + // family
- "00" + // pad1
- "0000" + // pad2
- "0e000000" + // interface index (14)
- "0800" + // NUD state (0x08 == NUD_DELAY)
- "00" + // flags
- "00" + // type
- // struct nlattr: NDA_DST
- "0800" + // length = 8
- "0100" + // type (1 == NDA_DST, for neighbor messages)
- "7f000001" + // IPv4 address (== 127.0.0.1)
- // struct nlattr: NDA_LLADDR
- "0a00" + // length = 10
- "0200" + // type (2 == NDA_LLADDR, for neighbor messages)
- "010203040506" + // MAC Address (== 01:02:03:04:05:06)
- "0000"; // padding, for 4 byte alignment
- final byte[] expectedNewNeigh =
- HexEncoding.decode(expectedNewNeighHex.toCharArray(), false);
-
- final byte[] bytes = RtNetlinkNeighborMessage.newNewNeighborMessage(
- seqNo, Inet4Address.LOOPBACK, StructNdMsg.NUD_DELAY, ifIndex, llAddr);
- if (!Arrays.equals(expectedNewNeigh, bytes)) {
- assertEquals(expectedNewNeigh.length, bytes.length);
- for (int i = 0; i < Math.min(expectedNewNeigh.length, bytes.length); i++) {
- assertEquals(expectedNewNeigh[i], bytes[i]);
- }
- }
- }
-}
diff --git a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java
deleted file mode 100644
index 0f3020d..0000000
--- a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java
+++ /dev/null
@@ -1,201 +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.netlink;
-
-import static android.net.netlink.StructNdOptPref64.getScaledLifetimePlc;
-import static android.net.netlink.StructNdOptPref64.plcToPrefixLength;
-import static android.net.netlink.StructNdOptPref64.prefixLengthToPlc;
-
-import static com.android.testutils.MiscAsserts.assertThrows;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import android.net.IpPrefix;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.util.HexEncoding;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.net.InetAddress;
-import java.nio.ByteBuffer;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class StructNdOptPref64Test {
-
- private static final String PREFIX1 = "64:ff9b::";
- private static final String PREFIX2 = "2001:db8:1:2:3:64::";
-
- private static byte[] prefixBytes(String addrString) throws Exception {
- InetAddress addr = InetAddress.getByName(addrString);
- byte[] prefixBytes = new byte[12];
- System.arraycopy(addr.getAddress(), 0, prefixBytes, 0, 12);
- return prefixBytes;
- }
-
- private static IpPrefix prefix(String addrString, int prefixLength) throws Exception {
- return new IpPrefix(InetAddress.getByName(addrString), prefixLength);
- }
-
- private void assertPref64OptMatches(int lifetime, IpPrefix prefix, StructNdOptPref64 opt) {
- assertEquals(StructNdOptPref64.TYPE, opt.type);
- assertEquals(2, opt.length);
- assertEquals(lifetime, opt.lifetime);
- assertEquals(prefix, opt.prefix);
- }
-
- private void assertToByteBufferMatches(StructNdOptPref64 opt, String expected) {
- String actual = HexEncoding.encodeToString(opt.toByteBuffer().array());
- assertEquals(expected, actual);
- }
-
- private ByteBuffer makeNdOptPref64(int lifetime, byte[] prefix, int prefixLengthCode) {
- if (prefix.length != 12) throw new IllegalArgumentException("Prefix must be 12 bytes");
-
- ByteBuffer buf = ByteBuffer.allocate(16)
- .put((byte) StructNdOptPref64.TYPE)
- .put((byte) StructNdOptPref64.LENGTH)
- .putShort(getScaledLifetimePlc(lifetime, prefixLengthCode))
- .put(prefix, 0, 12);
-
- buf.flip();
- return buf;
- }
-
- @Test
- public void testParseCannedOption() throws Exception {
- String hexBytes = "2602" // type=38, len=2 (16 bytes)
- + "0088" // lifetime=136, PLC=0 (/96)
- + "20010DB80003000400050006"; // 2001:db8:3:4:5:6/96
- byte[] rawBytes = HexEncoding.decode(hexBytes);
- StructNdOptPref64 opt = StructNdOptPref64.parse(ByteBuffer.wrap(rawBytes));
- assertPref64OptMatches(136, prefix("2001:DB8:3:4:5:6::", 96), opt);
- assertToByteBufferMatches(opt, hexBytes);
-
- hexBytes = "2602" // type=38, len=2 (16 bytes)
- + "2752" // lifetime=10064, PLC=2 (/56)
- + "0064FF9B0000000000000000"; // 64:ff9b::/56
- rawBytes = HexEncoding.decode(hexBytes);
- opt = StructNdOptPref64.parse(ByteBuffer.wrap(rawBytes));
- assertPref64OptMatches(10064, prefix("64:FF9B::", 56), opt);
- assertToByteBufferMatches(opt, hexBytes);
- }
-
- @Test
- public void testParsing() throws Exception {
- // Valid.
- ByteBuffer buf = makeNdOptPref64(600, prefixBytes(PREFIX1), 0);
- StructNdOptPref64 opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(600, prefix(PREFIX1, 96), opt);
-
- // Valid, zero lifetime, /64.
- buf = makeNdOptPref64(0, prefixBytes(PREFIX1), 1);
- opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(0, prefix(PREFIX1, 64), opt);
-
- // Valid, low lifetime, /56.
- buf = makeNdOptPref64(8, prefixBytes(PREFIX2), 2);
- opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(8, prefix(PREFIX2, 56), opt);
- assertEquals(new IpPrefix("2001:db8:1::/56"), opt.prefix); // Prefix is truncated.
-
- // Valid, maximum lifetime, /32.
- buf = makeNdOptPref64(65528, prefixBytes(PREFIX2), 5);
- opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(65528, prefix(PREFIX2, 32), opt);
- assertEquals(new IpPrefix("2001:db8::/32"), opt.prefix); // Prefix is truncated.
-
- // Lifetime not divisible by 8.
- buf = makeNdOptPref64(300, prefixBytes(PREFIX2), 0);
- opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(296, prefix(PREFIX2, 96), opt);
-
- // Invalid prefix length codes.
- buf = makeNdOptPref64(600, prefixBytes(PREFIX1), 6);
- assertNull(StructNdOptPref64.parse(buf));
- buf = makeNdOptPref64(600, prefixBytes(PREFIX1), 7);
- assertNull(StructNdOptPref64.parse(buf));
-
- // Truncated to varying lengths...
- buf = makeNdOptPref64(600, prefixBytes(PREFIX1), 3);
- final int len = buf.limit();
- for (int i = 0; i < buf.limit() - 1; i++) {
- buf.flip();
- buf.limit(i);
- assertNull("Option truncated to " + i + " bytes, should have returned null",
- StructNdOptPref64.parse(buf));
- }
- buf.flip();
- buf.limit(len);
- // ... but otherwise OK.
- opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(600, prefix(PREFIX1, 48), opt);
- }
-
- @Test
- public void testToString() throws Exception {
- ByteBuffer buf = makeNdOptPref64(600, prefixBytes(PREFIX1), 4);
- StructNdOptPref64 opt = StructNdOptPref64.parse(buf);
- assertPref64OptMatches(600, prefix(PREFIX1, 40), opt);
- assertEquals("NdOptPref64(64:ff9b::/40, 600)", opt.toString());
- }
-
- private void assertInvalidPlc(int plc) {
- assertThrows(IllegalArgumentException.class, () -> plcToPrefixLength(plc));
- }
-
- @Test
- public void testPrefixLengthToPlc() {
- for (int i = 0; i < 6; i++) {
- assertEquals(i, prefixLengthToPlc(plcToPrefixLength(i)));
- }
- assertInvalidPlc(-1);
- assertInvalidPlc(6);
- assertInvalidPlc(7);
- assertEquals(0, prefixLengthToPlc(96));
- }
-
-
- private void assertInvalidParameters(IpPrefix prefix, int lifetime) {
- assertThrows(IllegalArgumentException.class, () -> new StructNdOptPref64(prefix, lifetime));
- }
-
- @Test
- public void testToByteBuffer() throws Exception {
- final IpPrefix prefix1 = prefix(PREFIX1, 56);
- final IpPrefix prefix2 = prefix(PREFIX2, 96);
-
- StructNdOptPref64 opt = new StructNdOptPref64(prefix1, 600);
- assertToByteBufferMatches(opt, "2602025A0064FF9B0000000000000000");
- assertEquals(new IpPrefix("64:ff9b::/56"), opt.prefix);
- assertEquals(600, opt.lifetime);
-
- opt = new StructNdOptPref64(prefix2, 65519);
- assertToByteBufferMatches(opt, "2602FFE820010DB80001000200030064");
- assertEquals(new IpPrefix("2001:db8:1:2:3:64::/96"), opt.prefix);
- assertEquals(65512, opt.lifetime);
-
- assertInvalidParameters(prefix1, 65535);
- assertInvalidParameters(prefix2, -1);
- assertInvalidParameters(prefix("1.2.3.4", 32), 600);
- }
-}
diff --git a/tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java b/tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java
deleted file mode 100644
index b44b31d..0000000
--- a/tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.netlink;
-
-import static org.junit.Assert.fail;
-
-import android.system.OsConstants;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class StructNlMsgHdrTest {
-
- public static final short TEST_NLMSG_LEN = 16;
- public static final short TEST_NLMSG_FLAGS = StructNlMsgHdr.NLM_F_REQUEST
- | StructNlMsgHdr.NLM_F_MULTI | StructNlMsgHdr.NLM_F_ACK | StructNlMsgHdr.NLM_F_ECHO;
- public static final short TEST_NLMSG_SEQ = 1234;
- public static final short TEST_NLMSG_PID = 5678;
-
- // Checking the header string nlmsg_{len, ..} of the number can make sure that the checking
- // number comes from the expected element.
- // TODO: Verify more flags once StructNlMsgHdr can distinguish the flags which have the same
- // value. For example, NLM_F_MATCH (0x200) and NLM_F_EXCL (0x200) can't be distinguished.
- // See StructNlMsgHdrTest#stringForNlMsgFlags.
- public static final String TEST_NLMSG_LEN_STR = "nlmsg_len{16}";
- public static final String TEST_NLMSG_FLAGS_STR =
- "NLM_F_REQUEST|NLM_F_MULTI|NLM_F_ACK|NLM_F_ECHO";
- public static final String TEST_NLMSG_SEQ_STR = "nlmsg_seq{1234}";
- public static final String TEST_NLMSG_PID_STR = "nlmsg_pid{5678}";
-
- private StructNlMsgHdr makeStructNlMsgHdr(short type) {
- final StructNlMsgHdr struct = new StructNlMsgHdr();
- struct.nlmsg_len = TEST_NLMSG_LEN;
- struct.nlmsg_type = type;
- struct.nlmsg_flags = TEST_NLMSG_FLAGS;
- struct.nlmsg_seq = TEST_NLMSG_SEQ;
- struct.nlmsg_pid = TEST_NLMSG_PID;
- return struct;
- }
-
- private static void assertContains(String actualValue, String expectedSubstring) {
- if (actualValue.contains(expectedSubstring)) return;
- fail("\"" + actualValue + "\" does not contain \"" + expectedSubstring + "\"");
- }
-
- @Test
- public void testToString() {
- StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR);
- String s = struct.toString();
- assertContains(s, TEST_NLMSG_LEN_STR);
- assertContains(s, TEST_NLMSG_FLAGS_STR);
- assertContains(s, TEST_NLMSG_SEQ_STR);
- assertContains(s, TEST_NLMSG_PID_STR);
- assertContains(s, "nlmsg_type{20()}");
-
- struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY);
- s = struct.toString();
- assertContains(s, TEST_NLMSG_LEN_STR);
- assertContains(s, TEST_NLMSG_FLAGS_STR);
- assertContains(s, TEST_NLMSG_SEQ_STR);
- assertContains(s, TEST_NLMSG_PID_STR);
- assertContains(s, "nlmsg_type{20()}");
- }
-
- @Test
- public void testToStringWithNetlinkFamily() {
- StructNlMsgHdr struct = makeStructNlMsgHdr(NetlinkConstants.RTM_NEWADDR);
- String s = struct.toString(OsConstants.NETLINK_ROUTE);
- assertContains(s, TEST_NLMSG_LEN_STR);
- assertContains(s, TEST_NLMSG_FLAGS_STR);
- assertContains(s, TEST_NLMSG_SEQ_STR);
- assertContains(s, TEST_NLMSG_PID_STR);
- assertContains(s, "nlmsg_type{20(RTM_NEWADDR)}");
-
- struct = makeStructNlMsgHdr(NetlinkConstants.SOCK_DIAG_BY_FAMILY);
- s = struct.toString(OsConstants.NETLINK_INET_DIAG);
- assertContains(s, TEST_NLMSG_LEN_STR);
- assertContains(s, TEST_NLMSG_FLAGS_STR);
- assertContains(s, TEST_NLMSG_SEQ_STR);
- assertContains(s, TEST_NLMSG_PID_STR);
- assertContains(s, "nlmsg_type{20(SOCK_DIAG_BY_FAMILY)}");
- }
-}
diff --git a/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java b/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
index 436b81a..716abaa 100644
--- a/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
+++ b/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
@@ -17,12 +17,22 @@
package android.net.shared;
import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.ip.IIpClient.PROV_IPV4_DHCP;
+import static android.net.ip.IIpClient.PROV_IPV4_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV4_STATIC;
+import static android.net.ip.IIpClient.PROV_IPV6_DISABLED;
+import static android.net.ip.IIpClient.PROV_IPV6_LINKLOCAL;
+import static android.net.ip.IIpClient.PROV_IPV6_SLAAC;
import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
+import static android.net.shared.ProvisioningConfiguration.ipv4ProvisioningModeToString;
+import static android.net.shared.ProvisioningConfiguration.ipv6ProvisioningModeToString;
import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import android.net.LinkAddress;
import android.net.MacAddress;
@@ -76,32 +86,66 @@
return options;
}
- @Before
- public void setUp() {
- mConfig = new ProvisioningConfiguration();
- mConfig.mEnableIPv4 = true;
- mConfig.mEnableIPv6 = true;
- mConfig.mUsingMultinetworkPolicyTracker = true;
- mConfig.mUsingIpReachabilityMonitor = true;
- mConfig.mRequestedPreDhcpActionMs = 42;
- mConfig.mInitialConfig = new InitialConfiguration();
- mConfig.mInitialConfig.ipAddresses.add(
+ private ProvisioningConfiguration makeTestProvisioningConfiguration() {
+ final ProvisioningConfiguration config = new ProvisioningConfiguration();
+ config.mUsingMultinetworkPolicyTracker = true;
+ config.mUsingIpReachabilityMonitor = true;
+ config.mRequestedPreDhcpActionMs = 42;
+ config.mInitialConfig = new InitialConfiguration();
+ config.mInitialConfig.ipAddresses.add(
new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
- mConfig.mStaticIpConfig = new StaticIpConfiguration();
- mConfig.mStaticIpConfig.ipAddress =
+ config.mStaticIpConfig = new StaticIpConfiguration();
+ config.mStaticIpConfig.ipAddress =
new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
// Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
- mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3);
- mConfig.mProvisioningTimeoutMs = 4200;
- mConfig.mIPv6AddrGenMode = 123;
- mConfig.mNetwork = new Network(321);
- mConfig.mDisplayName = "test_config";
- mConfig.mEnablePreconnection = false;
- mConfig.mScanResultInfo = makeScanResultInfo("ssid");
- mConfig.mLayer2Info = new Layer2Information("some l2key", "some cluster",
+ config.mApfCapabilities = new ApfCapabilities(1, 2, 3);
+ config.mProvisioningTimeoutMs = 4200;
+ config.mIPv6AddrGenMode = 123;
+ config.mNetwork = new Network(321);
+ config.mDisplayName = "test_config";
+ config.mEnablePreconnection = false;
+ config.mScanResultInfo = makeScanResultInfo("ssid");
+ config.mLayer2Info = new Layer2Information("some l2key", "some cluster",
MacAddress.fromString("00:01:02:03:04:05"));
- mConfig.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
+ config.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
new String("android-dhcp-11").getBytes());
+ config.mIPv4ProvisioningMode = PROV_IPV4_DHCP;
+ config.mIPv6ProvisioningMode = PROV_IPV6_SLAAC;
+ return config;
+ }
+
+ private ProvisioningConfigurationParcelable makeTestProvisioningConfigurationParcelable() {
+ final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
+ p.enableIPv4 = true;
+ p.enableIPv6 = true;
+ p.usingMultinetworkPolicyTracker = true;
+ p.usingIpReachabilityMonitor = true;
+ p.requestedPreDhcpActionMs = 42;
+ final InitialConfiguration initialConfig = new InitialConfiguration();
+ initialConfig.ipAddresses.add(
+ new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
+ p.initialConfig = initialConfig.toStableParcelable();
+ p.staticIpConfig = new StaticIpConfiguration();
+ p.staticIpConfig.ipAddress =
+ new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
+ p.apfCapabilities = new ApfCapabilities(1, 2, 3);
+ p.provisioningTimeoutMs = 4200;
+ p.ipv6AddrGenMode = 123;
+ p.network = new Network(321);
+ p.displayName = "test_config";
+ p.enablePreconnection = false;
+ final ScanResultInfo scanResultInfo = makeScanResultInfo("ssid");
+ p.scanResultInfo = scanResultInfo.toStableParcelable();
+ final Layer2Information layer2Info = new Layer2Information("some l2key", "some cluster",
+ MacAddress.fromString("00:01:02:03:04:05"));
+ p.layer2Info = layer2Info.toStableParcelable();
+ p.options = makeCustomizedDhcpOptions((byte) 60, new String("android-dhcp-11").getBytes());
+ return p;
+ }
+
+ @Before
+ public void setUp() {
+ mConfig = makeTestProvisioningConfiguration();
// Any added field must be included in equals() to be tested properly
assertFieldCountEquals(16, ProvisioningConfiguration.class);
}
@@ -153,9 +197,43 @@
doParcelUnparcelTest();
}
+ @Test
+ public void testParcelUnparcel_DisabledIpProvisioningMode() {
+ mConfig.mIPv4ProvisioningMode = PROV_IPV4_DISABLED;
+ mConfig.mIPv6ProvisioningMode = PROV_IPV6_DISABLED;
+ doParcelUnparcelTest();
+
+ assertFalse(mConfig.toStableParcelable().enableIPv4);
+ assertFalse(mConfig.toStableParcelable().enableIPv6);
+ }
+
+ @Test
+ public void testParcelUnparcel_enabledIpProvisioningMode() {
+ mConfig.mIPv4ProvisioningMode = PROV_IPV4_DHCP;
+ mConfig.mIPv6ProvisioningMode = PROV_IPV6_SLAAC;
+ doParcelUnparcelTest();
+
+ assertTrue(mConfig.toStableParcelable().enableIPv4);
+ assertTrue(mConfig.toStableParcelable().enableIPv6);
+ }
+
+ @Test
+ public void testParcelUnparcel_IpProvisioningModefromOldStableParcelable() {
+ final ProvisioningConfigurationParcelable p = makeTestProvisioningConfigurationParcelable();
+ final ProvisioningConfiguration unparceled = fromStableParcelable(p,
+ 11 /* interface version */);
+ assertEquals(mConfig, unparceled);
+ }
+
+ @Test
+ public void testParcelUnparcel_WithIpv6LinkLocalOnly() {
+ mConfig.mIPv6ProvisioningMode = PROV_IPV6_LINKLOCAL;
+ doParcelUnparcelTest();
+ }
+
private void doParcelUnparcelTest() {
final ProvisioningConfiguration unparceled =
- fromStableParcelable(mConfig.toStableParcelable());
+ fromStableParcelable(mConfig.toStableParcelable(), 12 /* interface version */);
assertEquals(mConfig, unparceled);
}
@@ -163,8 +241,6 @@
public void testEquals() {
assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
- assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false);
- assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false);
assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
@@ -198,6 +274,10 @@
new String("vendor-class-identifier").getBytes()));
assertNotEqualsAfterChange(c -> c.mDhcpOptions = makeCustomizedDhcpOptions((byte) 77,
new String("vendor-class-identifier").getBytes()));
+ assertNotEqualsAfterChange(c -> c.mIPv4ProvisioningMode = PROV_IPV4_DISABLED);
+ assertNotEqualsAfterChange(c -> c.mIPv4ProvisioningMode = PROV_IPV4_STATIC);
+ assertNotEqualsAfterChange(c -> c.mIPv6ProvisioningMode = PROV_IPV6_DISABLED);
+ assertNotEqualsAfterChange(c -> c.mIPv6ProvisioningMode = PROV_IPV6_LINKLOCAL);
assertFieldCountEquals(16, ProvisioningConfiguration.class);
}
@@ -223,7 +303,8 @@
+ " android.net.Layer2InformationParcelable{l2Key: some l2key,"
+ " cluster: some cluster, bssid: %s},"
+ " options: [android.net.networkstack.aidl.dhcp.DhcpOption{type: 60,"
- + " value: [97, 110, 100, 114, 111, 105, 100, 45, 100, 104, 99, 112, 45, 49, 49]}]}";
+ + " value: [97, 110, 100, 114, 111, 105, 100, 45, 100, 104, 99, 112, 45, 49, 49]}],"
+ + " ipv4ProvisioningMode: 2, ipv6ProvisioningMode: 1}";
@Test
public void testParcelableToString() {
@@ -235,4 +316,17 @@
expected = String.format(TEMPLATE, "null");
assertEquals(expected, parcelWithNull.toString());
}
+
+ @Test
+ public void testIpProvisioningModeToString() {
+ assertEquals("disabled", ipv4ProvisioningModeToString(PROV_IPV4_DISABLED));
+ assertEquals("static", ipv4ProvisioningModeToString(PROV_IPV4_STATIC));
+ assertEquals("dhcp", ipv4ProvisioningModeToString(PROV_IPV4_DHCP));
+ assertEquals("unknown", ipv4ProvisioningModeToString(0x03 /* unknown mode */));
+
+ assertEquals("disabled", ipv6ProvisioningModeToString(PROV_IPV6_DISABLED));
+ assertEquals("slaac", ipv6ProvisioningModeToString(PROV_IPV6_SLAAC));
+ assertEquals("link-local", ipv6ProvisioningModeToString(PROV_IPV6_LINKLOCAL));
+ assertEquals("unknown", ipv6ProvisioningModeToString(0x03 /* unknown mode */));
+ }
}
diff --git a/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt b/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
index 5b91985..5ca20d8 100644
--- a/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
+++ b/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
@@ -1,5 +1,6 @@
package android.net.testutils
+import android.annotation.SuppressLint
import android.net.LinkAddress
import android.net.LinkProperties
import android.net.Network
@@ -7,6 +8,15 @@
import com.android.testutils.ConcurrentInterpreter
import com.android.testutils.InterpretMatcher
import com.android.testutils.RecorderCallback.CallbackEntry
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.AVAILABLE
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.BLOCKED_STATUS
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.LINK_PROPERTIES_CHANGED
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.LOSING
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.NETWORK_CAPS_UPDATED
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.LOST
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.RESUMED
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.SUSPENDED
+import com.android.testutils.RecorderCallback.CallbackEntry.Companion.UNAVAILABLE
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
@@ -33,6 +43,7 @@
const val TEST_INTERFACE_NAME = "testInterfaceName"
@RunWith(JUnit4::class)
+@SuppressLint("NewApi") // Uses hidden APIs, which the linter would identify as missing APIs.
class TestableNetworkCallbackTest {
private lateinit var mCallback: TestableNetworkCallback
@@ -102,6 +113,20 @@
}
@Test
+ fun testAssertNoCallbackThat() {
+ val net = Network(101)
+ mCallback.assertNoCallbackThat { it is Available }
+ mCallback.onAvailable(net)
+ // Expect no blocked status change. Receive other callback does not fail the test.
+ mCallback.assertNoCallbackThat { it is BlockedStatus }
+ mCallback.onBlockedStatusChanged(net, true)
+ assertFails { mCallback.assertNoCallbackThat { it is BlockedStatus } }
+ mCallback.onBlockedStatusChanged(net, false)
+ mCallback.onCapabilitiesChanged(net, NetworkCapabilities())
+ assertFails { mCallback.assertNoCallbackThat { it is CapabilitiesChanged } }
+ }
+
+ @Test
fun testCapabilitiesWithAndWithout() {
val net = Network(101)
val matcher = makeHasNetwork(101)
@@ -245,6 +270,41 @@
onBlockedStatus(199) | poll(1) = BlockedStatus(199) time 0..3
""")
}
+
+ @Test
+ fun testEventuallyExpect() {
+ // TODO: Current test does not verify the inline one. Also verify the behavior after
+ // aligning two eventuallyExpect()
+ val net1 = Network(100)
+ val net2 = Network(101)
+ mCallback.onAvailable(net1)
+ mCallback.onCapabilitiesChanged(net1, NetworkCapabilities())
+ mCallback.onLinkPropertiesChanged(net1, LinkProperties())
+ mCallback.eventuallyExpect(LINK_PROPERTIES_CHANGED) {
+ net1.equals(it.network)
+ }
+ // No further new callback. Expect no callback.
+ assertFails { mCallback.eventuallyExpect(LINK_PROPERTIES_CHANGED) }
+
+ // Verify no predicate set.
+ mCallback.onAvailable(net2)
+ mCallback.onLinkPropertiesChanged(net2, LinkProperties())
+ mCallback.onBlockedStatusChanged(net1, false)
+ mCallback.eventuallyExpect(BLOCKED_STATUS) { net1.equals(it.network) }
+ // Verify no callback received if the callback does not happen.
+ assertFails { mCallback.eventuallyExpect(LOSING) }
+ }
+
+ @Test
+ fun testEventuallyExpectOnMultiThreads() {
+ TNCInterpreter.interpretTestSpec(initial = mCallback, lineShift = 1,
+ threadTransform = { cb -> cb.createLinkedCopy() }, spec = """
+ onAvailable(100) | eventually(CapabilitiesChanged(100), 1) fails
+ sleep ; onCapabilitiesChanged(100) | eventually(CapabilitiesChanged(100), 2)
+ onAvailable(101) ; onBlockedStatus(101) | eventually(BlockedStatus(100), 2) fails
+ onSuspended(100) ; sleep ; onLost(100) | eventually(Lost(100), 2)
+ """)
+ }
}
private object TNCInterpreter : ConcurrentInterpreter<TestableNetworkCallback>(interpretTable)
@@ -254,6 +314,7 @@
return CallbackEntry::class.sealedSubclasses.first { it.simpleName == name }
}
+@SuppressLint("NewApi") // Uses hidden APIs, which the linter would identify as missing APIs.
private val interpretTable = listOf<InterpretMatcher<TestableNetworkCallback>>(
// Interpret "Available(xx)" as "call to onAvailable with netId xx", and likewise for
// all callback types. This is implemented above by enumerating the subclasses of
@@ -289,5 +350,26 @@
},
Regex("""poll\((\d+)\)""") to { i, cb, t ->
cb.pollForNextCallback(t.timeArg(1))
+ },
+ // Interpret "eventually(Available(xx), timeout)" as calling eventuallyExpect that expects
+ // CallbackEntry.AVAILABLE with netId of xx within timeout*INTERPRET_TIME_UNIT timeout, and
+ // likewise for all callback types.
+ Regex("""eventually\(($EntryList)\((\d+)\),\s+(\d+)\)""") to { i, cb, t ->
+ val net = Network(t.intArg(2))
+ val timeout = t.timeArg(3)
+ when (t.strArg(1)) {
+ "Available" -> cb.eventuallyExpect(AVAILABLE, timeout) { net == it.network }
+ "Suspended" -> cb.eventuallyExpect(SUSPENDED, timeout) { net == it.network }
+ "Resumed" -> cb.eventuallyExpect(RESUMED, timeout) { net == it.network }
+ "Losing" -> cb.eventuallyExpect(LOSING, timeout) { net == it.network }
+ "Lost" -> cb.eventuallyExpect(LOST, timeout) { net == it.network }
+ "Unavailable" -> cb.eventuallyExpect(UNAVAILABLE, timeout) { net == it.network }
+ "BlockedStatus" -> cb.eventuallyExpect(BLOCKED_STATUS, timeout) { net == it.network }
+ "CapabilitiesChanged" ->
+ cb.eventuallyExpect(NETWORK_CAPS_UPDATED, timeout) { net == it.network }
+ "LinkPropertiesChanged" ->
+ cb.eventuallyExpect(LINK_PROPERTIES_CHANGED, timeout) { net == it.network }
+ else -> fail("Unknown callback type")
+ }
}
)
diff --git a/tests/unit/src/com/android/net/module/util/TrackRecordTest.kt b/tests/unit/src/com/android/net/module/util/TrackRecordTest.kt
deleted file mode 100644
index 9fb4d8c..0000000
--- a/tests/unit/src/com/android/net/module/util/TrackRecordTest.kt
+++ /dev/null
@@ -1,446 +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 com.android.net.module.util
-
-import com.android.testutils.ConcurrentInterpreter
-import com.android.testutils.InterpretException
-import com.android.testutils.InterpretMatcher
-import com.android.testutils.SyntaxException
-import com.android.testutils.__FILE__
-import com.android.testutils.__LINE__
-import com.android.testutils.intArg
-import com.android.testutils.strArg
-import com.android.testutils.timeArg
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-import java.util.concurrent.CyclicBarrier
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicInteger
-import kotlin.system.measureTimeMillis
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertNotEquals
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
-import kotlin.test.fail
-
-val TEST_VALUES = listOf(4, 13, 52, 94, 41, 68, 11, 13, 51, 0, 91, 94, 33, 98, 14)
-const val ABSENT_VALUE = 2
-// Caution in changing these : some tests rely on the fact that TEST_TIMEOUT > 2 * SHORT_TIMEOUT
-// and LONG_TIMEOUT > 2 * TEST_TIMEOUT
-const val SHORT_TIMEOUT = 40L // ms
-const val TEST_TIMEOUT = 200L // ms
-const val LONG_TIMEOUT = 5000L // ms
-
-@RunWith(JUnit4::class)
-class TrackRecordTest {
- @Test
- fun testAddAndSizeAndGet() {
- val repeats = 22 // arbitrary
- val record = ArrayTrackRecord<Int>()
- assertEquals(0, record.size)
- repeat(repeats) { i -> record.add(i + 2) }
- assertEquals(repeats, record.size)
- record.add(2)
- assertEquals(repeats + 1, record.size)
-
- assertEquals(11, record[9])
- assertEquals(11, record.getOrNull(9))
- assertEquals(2, record[record.size - 1])
- assertEquals(2, record.getOrNull(record.size - 1))
-
- assertFailsWith<IndexOutOfBoundsException> { record[800] }
- assertFailsWith<IndexOutOfBoundsException> { record[-1] }
- assertFailsWith<IndexOutOfBoundsException> { record[repeats + 1] }
- assertNull(record.getOrNull(800))
- assertNull(record.getOrNull(-1))
- assertNull(record.getOrNull(repeats + 1))
- assertNull(record.getOrNull(800) { true })
- assertNull(record.getOrNull(-1) { true })
- assertNull(record.getOrNull(repeats + 1) { true })
- }
-
- @Test
- fun testIndexOf() {
- val record = ArrayTrackRecord<Int>()
- TEST_VALUES.forEach { record.add(it) }
- with(record) {
- assertEquals(9, indexOf(0))
- assertEquals(9, lastIndexOf(0))
- assertEquals(1, indexOf(13))
- assertEquals(7, lastIndexOf(13))
- assertEquals(3, indexOf(94))
- assertEquals(11, lastIndexOf(94))
- assertEquals(-1, indexOf(ABSENT_VALUE))
- assertEquals(-1, lastIndexOf(ABSENT_VALUE))
- }
- }
-
- @Test
- fun testContains() {
- val record = ArrayTrackRecord<Int>()
- TEST_VALUES.forEach { record.add(it) }
- TEST_VALUES.forEach { assertTrue(record.contains(it)) }
- assertFalse(record.contains(ABSENT_VALUE))
- assertTrue(record.containsAll(TEST_VALUES))
- assertTrue(record.containsAll(TEST_VALUES.sorted()))
- assertTrue(record.containsAll(TEST_VALUES.sortedDescending()))
- assertTrue(record.containsAll(TEST_VALUES.distinct()))
- assertTrue(record.containsAll(TEST_VALUES.subList(0, TEST_VALUES.size / 2)))
- assertTrue(record.containsAll(TEST_VALUES.subList(0, TEST_VALUES.size / 2).sorted()))
- assertTrue(record.containsAll(listOf()))
- assertFalse(record.containsAll(listOf(ABSENT_VALUE)))
- assertFalse(record.containsAll(TEST_VALUES + listOf(ABSENT_VALUE)))
- }
-
- @Test
- fun testEmpty() {
- val record = ArrayTrackRecord<Int>()
- assertTrue(record.isEmpty())
- record.add(1)
- assertFalse(record.isEmpty())
- }
-
- @Test
- fun testIterate() {
- val record = ArrayTrackRecord<Int>()
- record.forEach { fail("Expected nothing to iterate") }
- TEST_VALUES.forEach { record.add(it) }
- // zip relies on the iterator (this calls extension function Iterable#zip(Iterable))
- record.zip(TEST_VALUES).forEach { assertEquals(it.first, it.second) }
- // Also test reverse iteration (to test hasPrevious() and friends)
- record.reversed().zip(TEST_VALUES.reversed()).forEach { assertEquals(it.first, it.second) }
- }
-
- @Test
- fun testIteratorIsSnapshot() {
- val record = ArrayTrackRecord<Int>()
- TEST_VALUES.forEach { record.add(it) }
- val iterator = record.iterator()
- val expectedSize = record.size
- record.add(ABSENT_VALUE)
- record.add(ABSENT_VALUE)
- var measuredSize = 0
- iterator.forEach {
- ++measuredSize
- assertNotEquals(ABSENT_VALUE, it)
- }
- assertEquals(expectedSize, measuredSize)
- }
-
- @Test
- fun testSublist() {
- val record = ArrayTrackRecord<Int>()
- TEST_VALUES.forEach { record.add(it) }
- assertEquals(record.subList(3, record.size - 3),
- TEST_VALUES.subList(3, TEST_VALUES.size - 3))
- }
-
- fun testPollReturnsImmediately(record: TrackRecord<Int>) {
- record.add(4)
- val elapsed = measureTimeMillis { assertEquals(4, record.poll(LONG_TIMEOUT, 0)) }
- // Should not have waited at all, in fact.
- assertTrue(elapsed < LONG_TIMEOUT)
- record.add(7)
- record.add(9)
- // Can poll multiple times for the same position, in whatever order
- assertEquals(9, record.poll(0, 2))
- assertEquals(7, record.poll(Long.MAX_VALUE, 1))
- assertEquals(9, record.poll(0, 2))
- assertEquals(4, record.poll(0, 0))
- assertEquals(9, record.poll(0, 2) { it > 5 })
- assertEquals(7, record.poll(0, 0) { it > 5 })
- }
-
- @Test
- fun testPollReturnsImmediately() {
- testPollReturnsImmediately(ArrayTrackRecord())
- testPollReturnsImmediately(ArrayTrackRecord<Int>().newReadHead())
- }
-
- @Test
- fun testPollTimesOut() {
- val record = ArrayTrackRecord<Int>()
- var delay = measureTimeMillis { assertNull(record.poll(SHORT_TIMEOUT, 0)) }
- assertTrue(delay >= SHORT_TIMEOUT, "Delay $delay < $SHORT_TIMEOUT")
- delay = measureTimeMillis { assertNull(record.poll(SHORT_TIMEOUT, 0) { it < 10 }) }
- assertTrue(delay >= SHORT_TIMEOUT)
- }
-
- @Test
- fun testConcurrentPollDisallowed() {
- val failures = AtomicInteger(0)
- val readHead = ArrayTrackRecord<Int>().newReadHead()
- val barrier = CyclicBarrier(2)
- Thread {
- barrier.await(LONG_TIMEOUT, TimeUnit.MILLISECONDS) // barrier 1
- try {
- readHead.poll(LONG_TIMEOUT)
- } catch (e: ConcurrentModificationException) {
- failures.incrementAndGet()
- // Unblock the other thread
- readHead.add(0)
- }
- }.start()
- barrier.await() // barrier 1
- try {
- readHead.poll(LONG_TIMEOUT)
- } catch (e: ConcurrentModificationException) {
- failures.incrementAndGet()
- // Unblock the other thread
- readHead.add(0)
- }
- // One of the threads must have gotten an exception.
- assertEquals(failures.get(), 1)
- }
-
- @Test
- fun testPollWakesUp() {
- val record = ArrayTrackRecord<Int>()
- val barrier = CyclicBarrier(2)
- Thread {
- barrier.await(LONG_TIMEOUT, TimeUnit.MILLISECONDS) // barrier 1
- barrier.await() // barrier 2
- Thread.sleep(SHORT_TIMEOUT * 2)
- record.add(31)
- }.start()
- barrier.await() // barrier 1
- // Should find the element in more than SHORT_TIMEOUT but less than TEST_TIMEOUT
- var delay = measureTimeMillis {
- barrier.await() // barrier 2
- assertEquals(31, record.poll(TEST_TIMEOUT, 0))
- }
- assertTrue(delay in SHORT_TIMEOUT..TEST_TIMEOUT)
- // Polling for an element already added in anothe thread (pos 0) : should return immediately
- delay = measureTimeMillis { assertEquals(31, record.poll(TEST_TIMEOUT, 0)) }
- assertTrue(delay < TEST_TIMEOUT, "Delay $delay > $TEST_TIMEOUT")
- // Waiting for an element that never comes
- delay = measureTimeMillis { assertNull(record.poll(SHORT_TIMEOUT, 1)) }
- assertTrue(delay >= SHORT_TIMEOUT, "Delay $delay < $SHORT_TIMEOUT")
- // Polling for an element that doesn't match what is already there
- delay = measureTimeMillis { assertNull(record.poll(SHORT_TIMEOUT, 0) { it < 10 }) }
- assertTrue(delay >= SHORT_TIMEOUT)
- }
-
- // Just make sure the interpreter actually throws an exception when the spec
- // does not conform to the behavior. The interpreter is just a tool to test a
- // tool used for a tool for test, let's not have hundreds of tests for it ;
- // if it's broken one of the tests using it will break.
- @Test
- fun testInterpreter() {
- val interpretLine = __LINE__ + 2
- try {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- add(4) | poll(1, 0) = 5
- """)
- fail("This spec should have thrown")
- } catch (e: InterpretException) {
- assertTrue(e.cause is AssertionError)
- assertEquals(interpretLine + 1, e.stackTrace[0].lineNumber)
- assertTrue(e.stackTrace[0].fileName.contains(__FILE__))
- assertTrue(e.stackTrace[0].methodName.contains("testInterpreter"))
- assertTrue(e.stackTrace[0].methodName.contains("thread1"))
- }
- }
-
- @Test
- fun testMultipleAdds() {
- TRTInterpreter.interpretTestSpec(useReadHeads = false, spec = """
- add(2) | | |
- | add(4) | |
- | | add(6) |
- | | | add(8)
- poll(0, 0) = 2 time 0..1 | poll(0, 0) = 2 | poll(0, 0) = 2 | poll(0, 0) = 2
- poll(0, 1) = 4 time 0..1 | poll(0, 1) = 4 | poll(0, 1) = 4 | poll(0, 1) = 4
- poll(0, 2) = 6 time 0..1 | poll(0, 2) = 6 | poll(0, 2) = 6 | poll(0, 2) = 6
- poll(0, 3) = 8 time 0..1 | poll(0, 3) = 8 | poll(0, 3) = 8 | poll(0, 3) = 8
- """)
- }
-
- @Test
- fun testConcurrentAdds() {
- TRTInterpreter.interpretTestSpec(useReadHeads = false, spec = """
- add(2) | add(4) | add(6) | add(8)
- add(1) | add(3) | add(5) | add(7)
- poll(0, 1) is even | poll(0, 0) is even | poll(0, 3) is even | poll(0, 2) is even
- poll(0, 5) is odd | poll(0, 4) is odd | poll(0, 7) is odd | poll(0, 6) is odd
- """)
- }
-
- @Test
- fun testMultiplePoll() {
- TRTInterpreter.interpretTestSpec(useReadHeads = false, spec = """
- add(4) | poll(1, 0) = 4
- | poll(0, 1) = null time 0..1
- | poll(1, 1) = null time 1..2
- sleep; add(7) | poll(2, 1) = 7 time 1..2
- sleep; add(18) | poll(2, 2) = 18 time 1..2
- """)
- }
-
- @Test
- fun testMultiplePollWithPredicate() {
- TRTInterpreter.interpretTestSpec(useReadHeads = false, spec = """
- | poll(1, 0) = null | poll(1, 0) = null
- add(6) | poll(1, 0) = 6 |
- add(11) | poll(1, 0) { > 20 } = null | poll(1, 0) { = 11 } = 11
- | poll(1, 0) { > 8 } = 11 |
- """)
- }
-
- @Test
- fun testMultipleReadHeads() {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- | poll() = null | poll() = null | poll() = null
- add(5) | | poll() = 5 |
- | poll() = 5 | |
- add(8) | poll() = 8 | poll() = 8 |
- | | | poll() = 5
- | | | poll() = 8
- | | | poll() = null
- | | poll() = null |
- """)
- }
-
- @Test
- fun testReadHeadPollWithPredicate() {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- add(5) | poll() { < 0 } = null
- | poll() { > 5 } = null
- add(10) |
- | poll() { = 5 } = null // The "5" was skipped in the previous line
- add(15) | poll() { > 8 } = 15 // The "10" was skipped in the previous line
- | poll(1, 0) { > 8 } = 10 // 10 is the first element after pos 0 matching > 8
- """)
- }
-
- @Test
- fun testPollImmediatelyAdvancesReadhead() {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- add(1) | add(2) | add(3) | add(4)
- mark = 0 | poll(0) { > 3 } = 4 | |
- poll(0) { > 10 } = null | | |
- mark = 4 | | |
- poll() = null | | |
- """)
- }
-
- @Test
- fun testParallelReadHeads() {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- mark = 0 | mark = 0 | mark = 0 | mark = 0
- add(2) | | |
- | add(4) | |
- | | add(6) |
- | | | add(8)
- poll() = 2 | poll() = 2 | poll() = 2 | poll() = 2
- poll() = 4 | poll() = 4 | poll() = 4 | poll() = 4
- poll() = 6 | poll() = 6 | poll() = 6 | mark = 2
- poll() = 8 | poll() = 8 | mark = 3 | poll() = 6
- mark = 4 | mark = 4 | poll() = 8 | poll() = 8
- """)
- }
-
- @Test
- fun testPeek() {
- TRTInterpreter.interpretTestSpec(useReadHeads = true, spec = """
- add(2) | | |
- | add(4) | |
- | | add(6) |
- | | | add(8)
- peek() = 2 | poll() = 2 | poll() = 2 | peek() = 2
- peek() = 2 | peek() = 4 | poll() = 4 | peek() = 2
- peek() = 2 | peek() = 4 | peek() = 6 | poll() = 2
- peek() = 2 | mark = 1 | mark = 2 | poll() = 4
- mark = 0 | peek() = 4 | peek() = 6 | peek() = 6
- poll() = 2 | poll() = 4 | poll() = 6 | poll() = 6
- poll() = 4 | mark = 2 | poll() = 8 | peek() = 8
- peek() = 6 | peek() = 6 | peek() = null | mark = 3
- """)
- }
-}
-
-private object TRTInterpreter : ConcurrentInterpreter<TrackRecord<Int>>(interpretTable) {
- fun interpretTestSpec(spec: String, useReadHeads: Boolean) = if (useReadHeads) {
- interpretTestSpec(spec, initial = ArrayTrackRecord(),
- threadTransform = { (it as ArrayTrackRecord).newReadHead() })
- } else {
- interpretTestSpec(spec, ArrayTrackRecord())
- }
-}
-
-/*
- * Quick ref of supported expressions :
- * sleep(x) : sleeps for x time units and returns Unit ; sleep alone means sleep(1)
- * add(x) : calls and returns TrackRecord#add.
- * poll(time, pos) [{ predicate }] : calls and returns TrackRecord#poll(x time units, pos).
- * Optionally, a predicate may be specified.
- * poll() [{ predicate }] : calls and returns ReadHead#poll(1 time unit). Optionally, a predicate
- * may be specified.
- * EXPR = VALUE : asserts that EXPR equals VALUE. EXPR is interpreted. VALUE can either be the
- * string "null" or an int. Returns Unit.
- * EXPR time x..y : measures the time taken by EXPR and asserts it took at least x and at most
- * y time units.
- * predicate must be one of "= x", "< x" or "> x".
- */
-private val interpretTable = listOf<InterpretMatcher<TrackRecord<Int>>>(
- // Interpret "XXX is odd" : run XXX and assert its return value is odd ("even" works too)
- Regex("(.*)\\s+is\\s+(even|odd)") to { i, t, r ->
- i.interpret(r.strArg(1), t).also {
- assertEquals((it as Int) % 2, if ("even" == r.strArg(2)) 0 else 1)
- }
- },
- // Interpret "add(XXX)" as TrackRecord#add(int)
- Regex("""add\((\d+)\)""") to { i, t, r ->
- t.add(r.intArg(1))
- },
- // Interpret "poll(x, y)" as TrackRecord#poll(timeout = x * INTERPRET_TIME_UNIT, pos = y)
- // Accepts an optional {} argument for the predicate (see makePredicate for syntax)
- Regex("""poll\((\d+),\s*(\d+)\)\s*(\{.*\})?""") to { i, t, r ->
- t.poll(r.timeArg(1), r.intArg(2), makePredicate(r.strArg(3)))
- },
- // ReadHead#poll. If this throws in the cast, the code is malformed and has passed "poll()"
- // in a test that takes a TrackRecord that is not a ReadHead. It's technically possible to get
- // the test code to not compile instead of throw, but it's vastly more complex and this will
- // fail 100% at runtime any test that would not have compiled.
- Regex("""poll\((\d+)?\)\s*(\{.*\})?""") to { i, t, r ->
- (if (r.strArg(1).isEmpty()) i.interpretTimeUnit else r.timeArg(1)).let { time ->
- (t as ArrayTrackRecord<Int>.ReadHead).poll(time, makePredicate(r.strArg(2)))
- }
- },
- // ReadHead#mark. The same remarks apply as with ReadHead#poll.
- Regex("mark") to { i, t, _ -> (t as ArrayTrackRecord<Int>.ReadHead).mark },
- // ReadHead#peek. The same remarks apply as with ReadHead#poll.
- Regex("peek\\(\\)") to { i, t, _ -> (t as ArrayTrackRecord<Int>.ReadHead).peek() }
-)
-
-// Parses a { = x } or { < x } or { > x } string and returns the corresponding predicate
-// Returns an always-true predicate for empty and null arguments
-private fun makePredicate(spec: String?): (Int) -> Boolean {
- if (spec.isNullOrEmpty()) return { true }
- val match = Regex("""\{\s*([<>=])\s*(\d+)\s*\}""").matchEntire(spec)
- ?: throw SyntaxException("Predicate \"${spec}\"")
- val arg = match.intArg(2)
- return when (match.strArg(1)) {
- ">" -> { i -> i > arg }
- "<" -> { i -> i < arg }
- "=" -> { i -> i == arg }
- else -> throw RuntimeException("How did \"${spec}\" match this regexp ?")
- }
-}
diff --git a/tests/unit/src/com/android/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java b/tests/unit/src/com/android/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java
new file mode 100644
index 0000000..45592aa
--- /dev/null
+++ b/tests/unit/src/com/android/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.metrics;
+
+import android.stats.connectivity.IpType;
+import android.stats.connectivity.NudEventType;
+import android.stats.connectivity.NudNeighborType;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for IpReachabilityMonitorMetrics.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkIpReachabilityMonitorMetricsTest {
+ @Test
+ public void testIpReachabilityMonitorMetrics_setIpType() throws Exception {
+ NetworkIpReachabilityMonitorReported mStats;
+ final IpReachabilityMonitorMetrics mMetrics = new IpReachabilityMonitorMetrics();
+
+ for (IpType ip : IpType.values()) {
+ mMetrics.setNudIpType(ip);
+ mStats = mMetrics.statsWrite();
+ assertEquals(ip, mStats.getIpType());
+ }
+ }
+
+ @Test
+ public void testIpReachabilityMonitorMetrics_setNeighborType() throws Exception {
+ NetworkIpReachabilityMonitorReported mStats;
+ final IpReachabilityMonitorMetrics mMetrics = new IpReachabilityMonitorMetrics();
+
+ for (NudNeighborType neighborType : NudNeighborType.values()) {
+ mMetrics.setNudNeighborType(neighborType);
+ mStats = mMetrics.statsWrite();
+ assertEquals(neighborType, mStats.getNeighborType());
+ }
+ }
+
+ @Test
+ public void testIpReachabilityMonitorMetrics_setEventType() {
+ NetworkIpReachabilityMonitorReported mStats;
+ final IpReachabilityMonitorMetrics mMetrics = new IpReachabilityMonitorMetrics();
+
+ for (NudEventType type : NudEventType.values()) {
+ mMetrics.setNudEventType(type);
+ mStats = mMetrics.statsWrite();
+ assertEquals(type, mStats.getEventType());
+ }
+ }
+}
diff --git a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
index 8fbe0c4..198ac99 100644
--- a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
+++ b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
@@ -16,7 +16,6 @@
package com.android.networkstack.netlink;
-import static android.net.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
import static android.net.util.DataStallUtils.CONFIG_TCP_PACKETS_FAIL_PERCENTAGE;
import static android.net.util.DataStallUtils.DEFAULT_TCP_PACKETS_FAIL_PERCENTAGE;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
@@ -26,6 +25,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.net.module.util.netlink.NetlinkConstants.SOCKDIAG_MSG_HEADER_SIZE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -43,7 +43,6 @@
import android.net.INetd;
import android.net.MarkMaskParcel;
import android.net.Network;
-import android.net.netlink.StructNlMsgHdr;
import android.os.Build;
import android.util.Log;
import android.util.Log.TerribleFailureHandler;
@@ -51,6 +50,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.net.module.util.netlink.StructNlMsgHdr;
import com.android.networkstack.apishim.ConstantsShim;
import com.android.networkstack.apishim.NetworkShimImpl;
import com.android.testutils.DevSdkIgnoreRule;
diff --git a/tests/unit/src/com/android/networkstack/packets/NeighborAdvertisementTest.java b/tests/unit/src/com/android/networkstack/packets/NeighborAdvertisementTest.java
new file mode 100644
index 0000000..c689d7b
--- /dev/null
+++ b/tests/unit/src/com/android/networkstack/packets/NeighborAdvertisementTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.packets;
+
+import static android.system.OsConstants.ETH_P_IPV6;
+import static android.system.OsConstants.IPPROTO_ICMPV6;
+
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_TLLA;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_ROUTERS_MULTICAST;
+import static com.android.testutils.MiscAsserts.assertThrows;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.net.InetAddresses;
+import android.net.MacAddress;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.Inet6Address;
+import java.nio.ByteBuffer;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class NeighborAdvertisementTest {
+ private static final Inet6Address TEST_SRC_ADDR =
+ (Inet6Address) InetAddresses.parseNumericAddress("fe80::dfd9:50a0:cc7b:7d6d");
+ private static final Inet6Address TEST_TARGET_ADDR =
+ (Inet6Address) InetAddresses.parseNumericAddress("2001:db8:1:0:c928:250d:b90c:3178");
+ private static final byte[] TEST_SOURCE_MAC_ADDR = new byte[] {
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25
+ };
+ private static final byte[] TEST_DST_MAC_ADDR = new byte[] {
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ };
+ private static final byte[] TEST_GRATUITOUS_NA = new byte[] {
+ // dst mac address
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // src mac address
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xdf, (byte) 0xd9, (byte) 0x50, (byte) 0xa0,
+ (byte) 0xcc, (byte) 0x7b, (byte) 0x7d, (byte) 0x6d,
+ // destination address
+ (byte) 0xff, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+ // ICMP type, code, checksum
+ (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
+ // flags
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ (byte) 0xc9, (byte) 0x28, (byte) 0x25, (byte) 0x0d,
+ (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
+ // TLLA option
+ (byte) 0x02, (byte) 0x01,
+ // Link-Layer address
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
+ };
+ private static final byte[] TEST_GRATUITOUS_NA_WITHOUT_TLLA = new byte[] {
+ // dst mac address
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // src mac address
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xdf, (byte) 0xd9, (byte) 0x50, (byte) 0xa0,
+ (byte) 0xcc, (byte) 0x7b, (byte) 0x7d, (byte) 0x6d,
+ // destination address
+ (byte) 0xff, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+ // ICMP type, code, checksum
+ (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
+ // flags
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ (byte) 0xc9, (byte) 0x28, (byte) 0x25, (byte) 0x0d,
+ (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
+ };
+ private static final byte[] TEST_GRATUITOUS_NA_LESS_LENGTH = new byte[] {
+ // dst mac address
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // src mac address
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xdf, (byte) 0xd9, (byte) 0x50, (byte) 0xa0,
+ (byte) 0xcc, (byte) 0x7b, (byte) 0x7d, (byte) 0x6d,
+ // destination address
+ (byte) 0xff, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+ // ICMP type, code, checksum
+ (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
+ // flags
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ };
+ private static final byte[] TEST_GRATUITOUS_NA_TRUNCATED = new byte[] {
+ // dst mac address
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ // src mac address
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25, (byte) 0xc1, (byte) 0x25,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xdf, (byte) 0xd9, (byte) 0x50, (byte) 0xa0,
+ (byte) 0xcc, (byte) 0x7b, (byte) 0x7d, (byte) 0x6d,
+ // destination address
+ (byte) 0xff, (byte) 0x02, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02,
+ // ICMP type, code, checksum
+ (byte) 0x88, (byte) 0x00, (byte) 0x3a, (byte) 0x3c,
+ // flags
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
+ (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ (byte) 0xc9, (byte) 0x28, (byte) 0x25, (byte) 0x0d,
+ (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
+ // TLLA option
+ (byte) 0x02, (byte) 0x01,
+ // truncatd Link-Layer address: 4bytes
+ (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25,
+ };
+
+ @Test
+ public void testGratuitousNa_build() throws Exception {
+ final ByteBuffer na = NeighborAdvertisement.build(
+ MacAddress.fromBytes(TEST_SOURCE_MAC_ADDR),
+ MacAddress.fromBytes(TEST_DST_MAC_ADDR),
+ TEST_SRC_ADDR, IPV6_ADDR_ALL_ROUTERS_MULTICAST, 0 /* flags */, TEST_TARGET_ADDR);
+ assertArrayEquals(na.array(), TEST_GRATUITOUS_NA);
+ }
+
+ private void assertNeighborAdvertisement(final NeighborAdvertisement na,
+ boolean hasTllaOption) {
+ assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.ethHdr.srcMac.toByteArray());
+ assertArrayEquals(TEST_DST_MAC_ADDR, na.ethHdr.dstMac.toByteArray());
+ assertEquals(ETH_P_IPV6, na.ethHdr.etherType);
+ assertEquals(IPPROTO_ICMPV6, na.ipv6Hdr.nextHeader);
+ assertEquals(0xff, na.ipv6Hdr.hopLimit);
+ assertEquals(IPV6_ADDR_ALL_ROUTERS_MULTICAST, na.ipv6Hdr.dstIp);
+ assertEquals(TEST_SRC_ADDR, na.ipv6Hdr.srcIp);
+ assertEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, na.icmpv6Hdr.type);
+ assertEquals(0, na.icmpv6Hdr.code);
+ assertEquals(0, na.naHdr.flags);
+ assertEquals(TEST_TARGET_ADDR, na.naHdr.target);
+ if (hasTllaOption) {
+ assertEquals(ICMPV6_ND_OPTION_TLLA, na.tlla.type);
+ assertEquals(1, na.tlla.length);
+ assertArrayEquals(TEST_SOURCE_MAC_ADDR, na.tlla.linkLayerAddress.toByteArray());
+ }
+ }
+
+ @Test
+ public void testGratuitousNa_parse() throws Exception {
+ final NeighborAdvertisement na = NeighborAdvertisement.parse(TEST_GRATUITOUS_NA,
+ TEST_GRATUITOUS_NA.length);
+
+ assertNeighborAdvertisement(na, true /* hasTllaOption */);
+ assertArrayEquals(TEST_GRATUITOUS_NA, na.toByteBuffer().array());
+ }
+
+ @Test
+ public void testGratuitousNa_parseWithoutTllaOption() throws Exception {
+ final NeighborAdvertisement na =
+ NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_WITHOUT_TLLA,
+ TEST_GRATUITOUS_NA_WITHOUT_TLLA.length);
+
+ assertNeighborAdvertisement(na, false /* hasTllaOption */);
+ assertArrayEquals(TEST_GRATUITOUS_NA_WITHOUT_TLLA, na.toByteBuffer().array());
+ }
+
+ @Test
+ public void testGratuitousNa_zeroPacketLength() throws Exception {
+ assertThrows(NeighborAdvertisement.ParseException.class,
+ () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA, 0));
+ }
+
+ @Test
+ public void testGratuitousNa_invalidByteBufferLength() throws Exception {
+ assertThrows(NeighborAdvertisement.ParseException.class,
+ () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_TRUNCATED,
+ TEST_GRATUITOUS_NA.length));
+ }
+
+ @Test
+ public void testGratuitousNa_lessPacketLength() throws Exception {
+ assertThrows(NeighborAdvertisement.ParseException.class,
+ () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_LESS_LENGTH,
+ TEST_GRATUITOUS_NA_LESS_LENGTH.length));
+ }
+
+ @Test
+ public void testGratuitousNa_truncatedPacket() throws Exception {
+ assertThrows(IllegalArgumentException.class,
+ () -> NeighborAdvertisement.parse(TEST_GRATUITOUS_NA_TRUNCATED,
+ TEST_GRATUITOUS_NA_TRUNCATED.length));
+ }
+}
diff --git a/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java b/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java
new file mode 100644
index 0000000..18a3ef3
--- /dev/null
+++ b/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.packets;
+
+import static android.system.OsConstants.ETH_P_IPV6;
+import static android.system.OsConstants.IPPROTO_ICMPV6;
+
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_SLLA;
+import static com.android.net.module.util.NetworkStackConstants.ICMPV6_NEIGHBOR_SOLICITATION;
+import static com.android.testutils.MiscAsserts.assertThrows;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.net.InetAddresses;
+import android.net.MacAddress;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.Inet6Address;
+import java.nio.ByteBuffer;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class NeighborSolicitationTest {
+ private static final Inet6Address TEST_SRC_ADDR =
+ (Inet6Address) InetAddresses.parseNumericAddress("fe80::d419:d664:df38:2f65");
+ private static final Inet6Address TEST_DST_ADDR =
+ (Inet6Address) InetAddresses.parseNumericAddress("fe80::200:1a:1122:3344");
+ private static final Inet6Address TEST_TARGET_ADDR =
+ (Inet6Address) InetAddresses.parseNumericAddress("fe80::200:1a:1122:3344");
+ private static final byte[] TEST_SOURCE_MAC_ADDR = new byte[] {
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02, (byte) 0x61, (byte) 0x11,
+ };
+ private static final byte[] TEST_DST_MAC_ADDR = new byte[] {
+ (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ };
+ private static final byte[] TEST_NEIGHBOR_SOLICITATION = new byte[] {
+ // dst mac address
+ (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // src mac address
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02, (byte) 0x61, (byte) 0x11,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xd4, (byte) 0x19, (byte) 0xd6, (byte) 0x64,
+ (byte) 0xdf, (byte) 0x38, (byte) 0x2f, (byte) 0x65,
+ // destination address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // ICMP type, code, checksum
+ (byte) 0x87, (byte) 0x00, (byte) 0x22, (byte) 0x96,
+ // reserved
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // slla option
+ (byte) 0x01, (byte) 0x01,
+ // link-layer address
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02,
+ (byte) 0x61, (byte) 0x11,
+ };
+ private static final byte[] TEST_NEIGHBOR_SOLICITATION_WITHOUT_SLLA = new byte[] {
+ // dst mac address
+ (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // src mac address
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02, (byte) 0x61, (byte) 0x11,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xd4, (byte) 0x19, (byte) 0xd6, (byte) 0x64,
+ (byte) 0xdf, (byte) 0x38, (byte) 0x2f, (byte) 0x65,
+ // destination address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // ICMP type, code, checksum
+ (byte) 0x87, (byte) 0x00, (byte) 0x22, (byte) 0x96,
+ // reserved
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ };
+ private static final byte[] TEST_NEIGHBOR_SOLICITATION_LESS_LENGTH = new byte[] {
+ // dst mac address
+ (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // src mac address
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02, (byte) 0x61, (byte) 0x11,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xd4, (byte) 0x19, (byte) 0xd6, (byte) 0x64,
+ (byte) 0xdf, (byte) 0x38, (byte) 0x2f, (byte) 0x65,
+ // destination address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // ICMP type, code, checksum
+ (byte) 0x87, (byte) 0x00, (byte) 0x22, (byte) 0x96,
+ // reserved
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ };
+ private static final byte[] TEST_NEIGHBOR_SOLICITATION_TRUNCATED = new byte[] {
+ // dst mac address
+ (byte) 0x00, (byte) 0x1a, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // src mac address
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02, (byte) 0x61, (byte) 0x11,
+ // ether type
+ (byte) 0x86, (byte) 0xdd,
+ // version, priority and flow label
+ (byte) 0x60, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // length
+ (byte) 0x00, (byte) 0x20,
+ // next header
+ (byte) 0x3a,
+ // hop limit
+ (byte) 0xff,
+ // source address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0xd4, (byte) 0x19, (byte) 0xd6, (byte) 0x64,
+ (byte) 0xdf, (byte) 0x38, (byte) 0x2f, (byte) 0x65,
+ // destination address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // ICMP type, code, checksum
+ (byte) 0x87, (byte) 0x00, (byte) 0x22, (byte) 0x96,
+ // reserved
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ // target address
+ (byte) 0xfe, (byte) 0x80, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x1a,
+ (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
+ // slla option
+ (byte) 0x01, (byte) 0x01,
+ // truncatd link-layer address: 4bytes
+ (byte) 0x06, (byte) 0x5a, (byte) 0xac, (byte) 0x02,
+ };
+
+ @Test
+ public void testNeighborSolicitation_build() throws Exception {
+ final ByteBuffer ns = NeighborSolicitation.build(
+ MacAddress.fromBytes(TEST_SOURCE_MAC_ADDR),
+ MacAddress.fromBytes(TEST_DST_MAC_ADDR),
+ TEST_SRC_ADDR, TEST_DST_ADDR, TEST_TARGET_ADDR);
+ assertArrayEquals(ns.array(), TEST_NEIGHBOR_SOLICITATION);
+ }
+
+ private void assertNeighborSolicitation(final NeighborSolicitation ns, boolean hasSllaOption) {
+ assertArrayEquals(TEST_SOURCE_MAC_ADDR, ns.ethHdr.srcMac.toByteArray());
+ assertArrayEquals(TEST_DST_MAC_ADDR, ns.ethHdr.dstMac.toByteArray());
+ assertEquals(ETH_P_IPV6, ns.ethHdr.etherType);
+ assertEquals(IPPROTO_ICMPV6, ns.ipv6Hdr.nextHeader);
+ assertEquals(0xff, ns.ipv6Hdr.hopLimit);
+ assertEquals(TEST_DST_ADDR, ns.ipv6Hdr.dstIp);
+ assertEquals(TEST_SRC_ADDR, ns.ipv6Hdr.srcIp);
+ assertEquals(ICMPV6_NEIGHBOR_SOLICITATION, ns.icmpv6Hdr.type);
+ assertEquals(0, ns.icmpv6Hdr.code);
+ assertEquals(TEST_TARGET_ADDR, ns.nsHdr.target);
+ if (hasSllaOption) {
+ assertEquals(ICMPV6_ND_OPTION_SLLA, ns.slla.type);
+ assertEquals(1, ns.slla.length);
+ assertEquals(MacAddress.fromBytes(TEST_SOURCE_MAC_ADDR), ns.slla.linkLayerAddress);
+ }
+ }
+
+ @Test
+ public void testNeighborSolicitation_parse() throws Exception {
+ final NeighborSolicitation ns = NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION,
+ TEST_NEIGHBOR_SOLICITATION.length);
+
+ assertNeighborSolicitation(ns, true /* hasSllaOption */);
+ assertArrayEquals(TEST_NEIGHBOR_SOLICITATION, ns.toByteBuffer().array());
+ }
+
+ @Test
+ public void testNeighborSolicitation_parseWithoutSllaOption() throws Exception {
+ final NeighborSolicitation ns =
+ NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION_WITHOUT_SLLA,
+ TEST_NEIGHBOR_SOLICITATION_WITHOUT_SLLA.length);
+
+ assertNeighborSolicitation(ns, false /* hasSllaOption */);
+ assertArrayEquals(TEST_NEIGHBOR_SOLICITATION_WITHOUT_SLLA, ns.toByteBuffer().array());
+ }
+
+ @Test
+ public void testNeighborSolicitation_invalidPacketLength() throws Exception {
+ assertThrows(NeighborSolicitation.ParseException.class,
+ () -> NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION, 0));
+ }
+
+ @Test
+ public void testNeighborSolicitation_invalidByteBufferLength() throws Exception {
+ assertThrows(NeighborSolicitation.ParseException.class,
+ () -> NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION_TRUNCATED,
+ TEST_NEIGHBOR_SOLICITATION.length));
+ }
+
+ @Test
+ public void testNeighborSolicitation_lessPacketLength() throws Exception {
+ assertThrows(NeighborSolicitation.ParseException.class,
+ () -> NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION_LESS_LENGTH,
+ TEST_NEIGHBOR_SOLICITATION_LESS_LENGTH.length));
+ }
+
+ @Test
+ public void testNeighborSolicitation_truncatedPacket() throws Exception {
+ assertThrows(IllegalArgumentException.class,
+ () -> NeighborSolicitation.parse(TEST_NEIGHBOR_SOLICITATION_TRUNCATED,
+ TEST_NEIGHBOR_SOLICITATION_TRUNCATED.length));
+ }
+}
diff --git a/tests/unit/src/com/android/server/NetworkStackServiceTest.kt b/tests/unit/src/com/android/server/NetworkStackServiceTest.kt
index b32a419..cf65cd7 100644
--- a/tests/unit/src/com/android/server/NetworkStackServiceTest.kt
+++ b/tests/unit/src/com/android/server/NetworkStackServiceTest.kt
@@ -43,7 +43,6 @@
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
-import com.android.testutils.ExceptionUtils
import com.android.testutils.assertThrows
import org.junit.Rule
import org.junit.Test
@@ -207,10 +206,10 @@
verify(mockDhcpCb, times(2)).onDhcpServerCreated(eq(IDhcpServer.STATUS_SUCCESS), any())
// allowTestUid does not need to record the caller's version
- assertThrows(SecurityException::class.java, ExceptionUtils.ThrowingRunnable {
+ assertThrows(SecurityException::class.java) {
// Should throw because the test does not run as root
connector.allowTestUid(Process.myUid(), null)
- })
+ }
// Verify all methods were covered by the test (5 methods + getVersion + getHash)
assertEquals(7, INetworkStackConnector::class.declaredMemberFunctions.count {
diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index 8f42a61..ff43325 100644
--- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -16,7 +16,9 @@
package com.android.server.connectivity;
+import static android.content.Intent.ACTION_CONFIGURATION_CHANGED;
import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
+import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
import static android.net.DnsResolver.TYPE_A;
import static android.net.DnsResolver.TYPE_AAAA;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
@@ -25,9 +27,14 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_SKIPPED;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -91,6 +98,7 @@
import static java.util.stream.Collectors.toList;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -142,7 +150,11 @@
import com.android.networkstack.R;
import com.android.networkstack.apishim.CaptivePortalDataShimImpl;
import com.android.networkstack.apishim.ConstantsShim;
+import com.android.networkstack.apishim.NetworkInformationShimImpl;
+import com.android.networkstack.apishim.common.CaptivePortalDataShim;
+import com.android.networkstack.apishim.common.NetworkInformationShim;
import com.android.networkstack.apishim.common.ShimUtils;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.metrics.DataStallDetectionStats;
import com.android.networkstack.metrics.DataStallStatsUtils;
import com.android.networkstack.netlink.TcpSocketTracker;
@@ -151,6 +163,7 @@
import com.android.server.connectivity.nano.DnsEvent;
import com.android.server.connectivity.nano.WifiData;
import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.HandlerUtils;
@@ -197,6 +210,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@SuppressLint("NewApi") // Uses hidden APIs, which the linter would identify as missing APIs.
public class NetworkMonitorTest {
private static final String LOCATION_HEADER = "location";
private static final String CONTENT_TYPE_HEADER = "Content-Type";
@@ -261,6 +275,7 @@
private static final String TEST_SPEED_TEST_URL = "https://speedtest.example.com";
private static final String TEST_RELATIVE_URL = "/test/relative/gen_204";
private static final String TEST_MCCMNC = "123456";
+ private static final String TEST_FRIENDLY_NAME = "Friendly Name";
private static final String[] TEST_HTTP_URLS = {TEST_HTTP_OTHER_URL1, TEST_HTTP_OTHER_URL2};
private static final String[] TEST_HTTPS_URLS = {TEST_HTTPS_OTHER_URL1, TEST_HTTPS_OTHER_URL2};
private static final int TEST_TCP_FAIL_RATE = 99;
@@ -278,7 +293,9 @@
private static final int DEFAULT_DNS_TIMEOUT_THRESHOLD = 5;
private static final int HANDLER_TIMEOUT_MS = 1000;
-
+ private static final int TEST_MIN_STALL_EVALUATE_INTERVAL_MS = 500;
+ private static final int STALL_EXPECTED_LAST_PROBE_TIME_MS =
+ TEST_MIN_STALL_EVALUATE_INTERVAL_MS + HANDLER_TIMEOUT_MS;
private static final LinkProperties TEST_LINK_PROPERTIES = new LinkProperties();
// Cannot have a static member for the LinkProperties with captive portal API information, as
@@ -308,6 +325,14 @@
private static final NetworkCapabilities CELL_NO_INTERNET_CAPABILITIES =
new NetworkCapabilities().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ private static final NetworkCapabilities WIFI_OEM_PAID_CAPABILITIES =
+ new NetworkCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .addCapability(NET_CAPABILITY_OEM_PAID)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+
/**
* Fakes DNS responses.
*
@@ -538,7 +563,7 @@
resetCallbacks();
- setMinDataStallEvaluateInterval(500);
+ setMinDataStallEvaluateInterval(TEST_MIN_STALL_EVALUATE_INTERVAL_MS);
setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS);
setValidDataStallDnsTimeThreshold(500);
setConsecutiveDnsTimeoutThreshold(5);
@@ -565,7 +590,7 @@
}
private void resetCallbacks() {
- resetCallbacks(6);
+ resetCallbacks(11);
}
private void resetCallbacks(int interfaceVersion) {
@@ -613,6 +638,7 @@
@Override
protected void onQuitting() {
+ super.onQuitting();
assertTrue(mCreatedNetworkMonitors.remove(this));
mQuitCv.open();
}
@@ -839,7 +865,6 @@
@Test
public void testGetHttpProbeUrl() {
- final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
// If config_captive_portal_http_url is set and the global setting is set, the config is
// used.
doReturn(TEST_HTTP_URL).when(mResources).getString(R.string.config_captive_portal_http_url);
@@ -847,16 +872,21 @@
R.string.default_captive_portal_http_url);
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
.thenReturn(TEST_HTTP_OTHER_URL1);
- assertEquals(TEST_HTTP_URL, wnm.getCaptivePortalServerHttpUrl());
+ final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
+ assertEquals(TEST_HTTP_URL, wnm.getCaptivePortalServerHttpUrl(mContext));
// If config_captive_portal_http_url is unset and the global setting is set, the global
// setting is used.
doReturn(null).when(mResources).getString(R.string.config_captive_portal_http_url);
- assertEquals(TEST_HTTP_OTHER_URL1, wnm.getCaptivePortalServerHttpUrl());
+ assertEquals(TEST_HTTP_OTHER_URL1, wnm.getCaptivePortalServerHttpUrl(mContext));
// If both config_captive_portal_http_url and global setting are unset,
- // default_captive_portal_http_url is used.
+ // default_captive_portal_http_url is used. But the global setting will only be read in the
+ // constructor.
when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
.thenReturn(null);
- assertEquals(TEST_HTTP_OTHER_URL2, wnm.getCaptivePortalServerHttpUrl());
+ assertEquals(TEST_HTTP_OTHER_URL1, wnm.getCaptivePortalServerHttpUrl(mContext));
+ // default_captive_portal_http_url is used when the configuration is applied in new NM.
+ final WrappedNetworkMonitor wnm2 = makeCellNotMeteredNetworkMonitor();
+ assertEquals(TEST_HTTP_OTHER_URL2, wnm2.getCaptivePortalServerHttpUrl(mContext));
}
@Test
@@ -913,6 +943,57 @@
}
}
+ @Test
+ public void testConfigurationChange_BeforeNMConnected() throws Exception {
+ final WrappedNetworkMonitor nm = new WrappedNetworkMonitor();
+ final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ // Verify configuration change receiver is registered after start().
+ verify(mContext, never()).registerReceiver(receiverCaptor.capture(),
+ argThat(receiver -> ACTION_CONFIGURATION_CHANGED.equals(receiver.getAction(0))));
+ nm.start();
+ mCreatedNetworkMonitors.add(nm);
+ HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
+ verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(),
+ argThat(receiver -> ACTION_CONFIGURATION_CHANGED.equals(receiver.getAction(0))));
+ // Update a new URL and send a configuration change
+ doReturn(TEST_HTTPS_OTHER_URL1).when(mResources).getString(
+ R.string.config_captive_portal_https_url);
+ receiverCaptor.getValue().onReceive(mContext, new Intent(ACTION_CONFIGURATION_CHANGED));
+ HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
+ // Should stay in default state before receiving CMD_NETWORK_CONNECTED
+ verify(mOtherHttpsConnection1, never()).getResponseCode();
+ }
+
+ @Test
+ public void testIsCaptivePortal_ConfigurationChange_RenewUrls() throws Exception {
+ setStatus(mHttpsConnection, 204);
+ final NetworkMonitor nm = runValidatedNetworkTest();
+ final ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext, times(1)).registerReceiver(receiverCaptor.capture(),
+ argThat(receiver -> ACTION_CONFIGURATION_CHANGED.equals(receiver.getAction(0))));
+
+ resetCallbacks();
+ // New URLs with partial connectivity
+ doReturn(TEST_HTTPS_OTHER_URL1).when(mResources).getString(
+ R.string.config_captive_portal_https_url);
+ doReturn(TEST_HTTP_OTHER_URL1).when(mResources).getString(
+ R.string.config_captive_portal_http_url);
+ setStatus(mOtherHttpsConnection1, 500);
+ setStatus(mOtherHttpConnection1, 204);
+
+ // Receive configuration. Expect a reevaluation triggered.
+ receiverCaptor.getValue().onReceive(mContext, new Intent(ACTION_CONFIGURATION_CHANGED));
+
+ HandlerUtils.waitForIdle(nm.getHandler(), HANDLER_TIMEOUT_MS);
+ verifyNetworkTested(NETWORK_VALIDATION_RESULT_PARTIAL,
+ NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP);
+ verify(mOtherHttpsConnection1, times(1)).getResponseCode();
+ verify(mOtherHttpConnection1, times(1)).getResponseCode();
+ }
+
private CellInfoGsm makeTestCellInfoGsm(String mcc) throws Exception {
final CellInfoGsm info = new CellInfoGsm();
final CellIdentityGsm ci = makeCellIdentityGsm(0, 0, 0, 0, mcc, "01", "", "");
@@ -943,7 +1024,7 @@
public void testMakeFallbackUrls() throws Exception {
final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
// Value exist in setting provider.
- URL[] urls = wnm.makeCaptivePortalFallbackUrls();
+ URL[] urls = wnm.makeCaptivePortalFallbackUrls(mContext);
assertEquals(urls[0].toString(), TEST_FALLBACK_URL);
// Clear setting provider value. Verify it to get configuration from resource instead.
@@ -951,13 +1032,13 @@
// Verify that getting resource with exception.
when(mResources.getStringArray(R.array.config_captive_portal_fallback_urls))
.thenThrow(Resources.NotFoundException.class);
- urls = wnm.makeCaptivePortalFallbackUrls();
+ urls = wnm.makeCaptivePortalFallbackUrls(mContext);
assertEquals(urls.length, 0);
// Verify resource return 2 different URLs.
doReturn(new String[] {"http://testUrl1.com", "http://testUrl2.com"}).when(mResources)
.getStringArray(R.array.config_captive_portal_fallback_urls);
- urls = wnm.makeCaptivePortalFallbackUrls();
+ urls = wnm.makeCaptivePortalFallbackUrls(mContext);
assertEquals(urls.length, 2);
assertEquals("http://testUrl1.com", urls[0].toString());
assertEquals("http://testUrl2.com", urls[1].toString());
@@ -968,7 +1049,7 @@
setupNoSimCardNeighborMcc();
doReturn(new String[] {"http://testUrl3.com"}).when(mMccResource)
.getStringArray(R.array.config_captive_portal_fallback_urls);
- urls = wnm.makeCaptivePortalFallbackUrls();
+ urls = wnm.makeCaptivePortalFallbackUrls(mContext);
assertEquals(urls.length, 2);
assertEquals("http://testUrl1.com", urls[0].toString());
assertEquals("http://testUrl2.com", urls[1].toString());
@@ -981,7 +1062,7 @@
doReturn(new String[] {"http://testUrl.com"}).when(mMccResource)
.getStringArray(R.array.config_captive_portal_fallback_urls);
final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
- final URL[] urls = wnm.makeCaptivePortalFallbackUrls();
+ final URL[] urls = wnm.makeCaptivePortalFallbackUrls(mMccContext);
assertEquals(urls.length, 1);
assertEquals("http://testUrl.com", urls[0].toString());
}
@@ -1061,6 +1142,34 @@
runPortalNetworkTest();
}
+ @Test
+ public void testIsCaptivePortal_Http200EmptyResponse() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 200);
+ // Invalid if there is no content (can't login to an empty page)
+ runNetworkTest(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null);
+ verify(mCallbacks, never()).showProvisioningNotification(any(), any());
+ }
+
+ private void doCaptivePortal200ResponseTest(String expectedRedirectUrl) throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 200);
+ doReturn(100L).when(mHttpConnection).getContentLengthLong();
+ // Redirect URL was null before S
+ runNetworkTest(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, expectedRedirectUrl);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).showProvisioningNotification(any(), any());
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.R)
+ public void testIsCaptivePortal_HttpProbeIs200Portal_R() throws Exception {
+ doCaptivePortal200ResponseTest(null);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testIsCaptivePortal_HttpProbeIs200Portal() throws Exception {
+ doCaptivePortal200ResponseTest(TEST_HTTP_URL);
+ }
+
private void setupPrivateIpResponse(String privateAddr) throws Exception {
setSslException(mHttpsConnection);
setPortal302(mHttpConnection);
@@ -1598,7 +1707,8 @@
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
assertFalse(wrappedMonitor.isDataStall());
- wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ wrappedMonitor.setLastProbeTime(
+ SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
assertTrue(wrappedMonitor.isDataStall());
verify(mCallbacks).notifyDataStallSuspected(
@@ -1608,7 +1718,8 @@
@Test
public void testIsDataStall_EvaluationDnsWithDnsTimeoutCount() throws Exception {
WrappedNetworkMonitor wrappedMonitor = makeCellMeteredNetworkMonitor();
- wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ wrappedMonitor.setLastProbeTime(
+ SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
makeDnsTimeoutEvent(wrappedMonitor, 3);
assertFalse(wrappedMonitor.isDataStall());
// Reset consecutive timeout counts.
@@ -1626,7 +1737,8 @@
// Set the value to larger than the default dns log size.
setConsecutiveDnsTimeoutThreshold(51);
wrappedMonitor = makeCellMeteredNetworkMonitor();
- wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ wrappedMonitor.setLastProbeTime(
+ SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
makeDnsTimeoutEvent(wrappedMonitor, 50);
assertFalse(wrappedMonitor.isDataStall());
@@ -1658,7 +1770,8 @@
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
assertFalse(wrappedMonitor.isDataStall());
- wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ wrappedMonitor.setLastProbeTime(
+ SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
assertTrue(wrappedMonitor.isDataStall());
verify(mCallbacks).notifyDataStallSuspected(
matchDnsDataStallParcelable(DEFAULT_DNS_TIMEOUT_THRESHOLD));
@@ -1669,7 +1782,8 @@
wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 100);
makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
assertFalse(wrappedMonitor.isDataStall());
- wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ wrappedMonitor.setLastProbeTime(
+ SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
assertFalse(wrappedMonitor.isDataStall());
}
@@ -1703,7 +1817,7 @@
setDataStallEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS | DATA_STALL_EVALUATION_TYPE_TCP);
setupTcpDataStall();
final WrappedNetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
- nm.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
makeDnsTimeoutEvent(nm, DEFAULT_DNS_TIMEOUT_THRESHOLD);
assertTrue(nm.isDataStall());
verify(mCallbacks).notifyDataStallSuspected(
@@ -1739,25 +1853,105 @@
runFailedNetworkTest();
}
- @Test
- public void testNoInternetCapabilityValidated() throws Exception {
- runNetworkTest(TEST_LINK_PROPERTIES, CELL_NO_INTERNET_CAPABILITIES,
- NETWORK_VALIDATION_RESULT_VALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+ private void doValidationSkippedTest(NetworkCapabilities nc, int validationResult)
+ throws Exception {
+ runNetworkTest(TEST_LINK_PROPERTIES, nc, validationResult,
+ 0 /* probesSucceeded */, null /* redirectUrl */);
verify(mCleartextDnsNetwork, never()).openConnection(any());
}
@Test
- public void testLaunchCaptivePortalApp() throws Exception {
+ public void testNoInternetCapabilityValidated() throws Exception {
+ doValidationSkippedTest(CELL_NO_INTERNET_CAPABILITIES,
+ NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED);
+ }
+
+ @Test
+ public void testNoInternetCapabilityValidated_OlderPlatform() throws Exception {
+ // Before callbacks version 11, NETWORK_VALIDATION_RESULT_SKIPPED is not sent
+ resetCallbacks(10);
+ doValidationSkippedTest(CELL_NO_INTERNET_CAPABILITIES, NETWORK_VALIDATION_RESULT_VALID);
+ }
+
+ @Test
+ public void testNoTrustedCapabilityValidated() throws Exception {
+ // Cannot use the NetworkCapabilities builder on Q
+ final NetworkCapabilities nc = new NetworkCapabilities()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .addTransportType(TRANSPORT_CELLULAR);
+ if (ShimUtils.isAtLeastS()) {
+ nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ }
+ doValidationSkippedTest(nc,
+ NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED);
+ }
+
+ @Test
+ public void testRestrictedCapabilityValidated() throws Exception {
+ // Cannot use the NetworkCapabilities builder on Q
+ final NetworkCapabilities nc = new NetworkCapabilities()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .addTransportType(TRANSPORT_CELLULAR);
+ if (ShimUtils.isAtLeastS()) {
+ nc.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ }
+ doValidationSkippedTest(nc,
+ NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED);
+ }
+
+ private NetworkCapabilities getVcnUnderlyingCarrierWifiCaps() {
+ // Must be called from within the test because NOT_VCN_MANAGED is an invalid capability
+ // value up to Android R. Thus, this must be guarded by an SDK check in tests that use this.
+ return new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ }
+
+ @Test
+ public void testVcnUnderlyingNetwork() throws Exception {
+ assumeTrue(ShimUtils.isAtLeastS());
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+
+ final NetworkMonitor nm = runNetworkTest(
+ TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
+ NETWORK_VALIDATION_RESULT_VALID,
+ NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
+ null /* redirectUrl */);
+ assertEquals(NETWORK_VALIDATION_RESULT_VALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
+ @Test
+ public void testVcnUnderlyingNetworkBadNetwork() throws Exception {
+ assumeTrue(ShimUtils.isAtLeastS());
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ final NetworkMonitor nm = runNetworkTest(
+ TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
+ VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+ assertEquals(VALIDATION_RESULT_INVALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
+ public void setupAndLaunchCaptivePortalApp(final NetworkMonitor nm) throws Exception {
setSslException(mHttpsConnection);
setPortal302(mHttpConnection);
when(mHttpConnection.getHeaderField(eq("location"))).thenReturn(TEST_LOGIN_URL);
- final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
notifyNetworkConnected(nm, CELL_METERED_CAPABILITIES);
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
.showProvisioningNotification(any(), any());
- assertEquals(1, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
// Check that startCaptivePortalApp sends the expected intent.
nm.launchCaptivePortalApp();
@@ -1778,17 +1972,49 @@
final String redirectUrl = bundle.getString(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL);
assertEquals(TEST_HTTP_URL, redirectUrl);
+ resetCallbacks();
+ }
+
+ @Test
+ public void testCaptivePortalLogin() throws Exception {
+ final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
+ setupAndLaunchCaptivePortalApp(nm);
+
// Have the app report that the captive portal is dismissed, and check that we revalidate.
setStatus(mHttpsConnection, 204);
setStatus(mHttpConnection, 204);
- resetCallbacks();
nm.notifyCaptivePortalAppFinished(APP_RETURN_DISMISSED);
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
.notifyNetworkTestedWithExtras(matchNetworkTestResultParcelable(
NETWORK_VALIDATION_RESULT_VALID,
NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP));
- assertEquals(0, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
+ }
+
+ @Test
+ public void testCaptivePortalUseAsIs() throws Exception {
+ final NetworkMonitor nm = makeMonitor(CELL_METERED_CAPABILITIES);
+ setupAndLaunchCaptivePortalApp(nm);
+
+ // The user decides this network is wanted as is, either by encountering an SSL error or
+ // encountering an unknown scheme and then deciding to continue through the browser, or by
+ // selecting this option through the options menu.
+ nm.notifyCaptivePortalAppFinished(APP_RETURN_WANTED_AS_IS);
+ // The captive portal is still closed, but the network validates since the user said so.
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
+ .notifyNetworkTestedWithExtras(matchNetworkTestResultParcelable(
+ NETWORK_VALIDATION_RESULT_VALID, 0 /* probesSucceeded */));
+ resetCallbacks();
+
+ // Revalidate.
+ nm.forceReevaluation(0 /* responsibleUid */);
+
+ // The network should still be valid.
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
+ .notifyNetworkTestedWithExtras(matchNetworkTestResultParcelable(
+ NETWORK_VALIDATION_RESULT_VALID, 0 /* probesSucceeded */,
+ TEST_LOGIN_URL));
}
@Test
@@ -1996,7 +2222,7 @@
nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
verifyNetworkTested(NETWORK_VALIDATION_RESULT_VALID,
NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS);
- nm.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
return nm;
}
@@ -2018,6 +2244,8 @@
ArgumentCaptor.forClass(DataStallDetectionStats.class);
verify(mDependencies, timeout(HANDLER_TIMEOUT_MS).times(1))
.writeDataStallDetectionStats(statsCaptor.capture(), probeResultCaptor.capture());
+ // Ensure probe will not stop due to rate-limiting mechanism.
+ nm.setLastProbeTime(SystemClock.elapsedRealtime() - STALL_EXPECTED_LAST_PROBE_TIME_MS);
assertTrue(nm.isDataStall());
assertTrue(probeResultCaptor.getValue().isSuccessful());
verifyTestDataStallDetectionStats(evalType, transport, statsCaptor.getValue());
@@ -2347,7 +2575,7 @@
verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
.showProvisioningNotification(any(), any());
- assertEquals(1, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
// Check that startCaptivePortalApp sends the expected intent.
nm.launchCaptivePortalApp();
@@ -2537,6 +2765,117 @@
verify(mCleartextDnsNetwork, times(4)).openConnection(any());
}
+ @Test
+ public void testIsCaptivePortal_FromExternalSource() throws Exception {
+ assumeTrue(CaptivePortalDataShimImpl.isSupported());
+ assumeTrue(ShimUtils.isAtLeastS());
+ when(mDependencies.isFeatureEnabled(any(), eq(NAMESPACE_CONNECTIVITY),
+ eq(DISMISS_PORTAL_IN_VALIDATED_NETWORK), anyBoolean())).thenReturn(true);
+ final NetworkMonitor monitor = makeMonitor(WIFI_NOT_METERED_CAPABILITIES);
+
+ NetworkInformationShim networkShim = NetworkInformationShimImpl.newInstance();
+ CaptivePortalDataShim captivePortalData = new CaptivePortalDataShimImpl(
+ new CaptivePortalData.Builder().setCaptive(true).build());
+ final LinkProperties linkProperties = new LinkProperties(TEST_LINK_PROPERTIES);
+ networkShim.setCaptivePortalData(linkProperties, captivePortalData);
+ CaptivePortalDataShim captivePortalDataShim =
+ networkShim.getCaptivePortalData(linkProperties);
+
+ try {
+ // Set up T&C captive portal info from Passpoint
+ captivePortalData = captivePortalDataShim.withPasspointInfo(TEST_FRIENDLY_NAME,
+ Uri.parse(TEST_VENUE_INFO_URL), Uri.parse(TEST_LOGIN_URL));
+ } catch (UnsupportedApiLevelException e) {
+ // Minimum API level for this test is 31
+ return;
+ }
+
+ networkShim.setCaptivePortalData(linkProperties, captivePortalData);
+ monitor.notifyLinkPropertiesChanged(linkProperties);
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities(WIFI_NOT_METERED_CAPABILITIES);
+ monitor.notifyNetworkConnected(linkProperties, networkCapabilities);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+ .showProvisioningNotification(any(), any());
+ assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
+ verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);
+
+ // Force reevaluation and confirm that the network is still captive
+ HandlerUtils.waitForIdle(monitor.getHandler(), HANDLER_TIMEOUT_MS);
+ resetCallbacks();
+ monitor.forceReevaluation(Process.myUid());
+ assertEquals(monitor.getEvaluationState().getProbeCompletedResult(), 0);
+ verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);
+
+ // Check that startCaptivePortalApp sends the expected intent.
+ monitor.launchCaptivePortalApp();
+
+ verify(mCm, timeout(HANDLER_TIMEOUT_MS).times(1)).startCaptivePortalApp(
+ argThat(network -> TEST_NETID == network.netId),
+ argThat(bundle -> bundle.getString(
+ ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL).equals(TEST_LOGIN_URL)
+ && TEST_NETID == ((Network) bundle.getParcelable(
+ ConnectivityManager.EXTRA_NETWORK)).netId));
+ }
+
+ @Test
+ public void testOemPaidNetworkValidated() throws Exception {
+ setValidProbes();
+
+ final NetworkMonitor nm = runNetworkTest(TEST_LINK_PROPERTIES,
+ WIFI_OEM_PAID_CAPABILITIES,
+ NETWORK_VALIDATION_RESULT_VALID,
+ NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
+ null /* redirectUrl */);
+ assertEquals(NETWORK_VALIDATION_RESULT_VALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
+ @Test
+ public void testOemPaidNetwork_AllProbesFailed() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ runNetworkTest(TEST_LINK_PROPERTIES,
+ WIFI_OEM_PAID_CAPABILITIES,
+ VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+ }
+
+ @Test
+ public void testOemPaidNetworkNoInternetCapabilityValidated() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities(WIFI_OEM_PAID_CAPABILITIES);
+ networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
+
+ final int validationResult =
+ NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_SKIPPED;
+ runNetworkTest(TEST_LINK_PROPERTIES, networkCapabilities,
+ validationResult, 0 /* probesSucceeded */, null /* redirectUrl */);
+
+ verify(mCleartextDnsNetwork, never()).openConnection(any());
+ verify(mHttpsConnection, never()).getResponseCode();
+ verify(mHttpConnection, never()).getResponseCode();
+ verify(mFallbackConnection, never()).getResponseCode();
+ }
+
+ @Test
+ public void testOemPaidNetwork_CaptivePortalNotLaunched() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mFallbackConnection, 404);
+ setPortal302(mHttpConnection);
+
+ runNetworkTest(TEST_LINK_PROPERTIES, WIFI_OEM_PAID_CAPABILITIES,
+ VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
+ TEST_LOGIN_URL);
+
+ verify(mCallbacks, never()).showProvisioningNotification(any(), any());
+ }
+
private void setupResourceForMultipleProbes() {
// Configure the resource to send multiple probe.
when(mResources.getStringArray(R.array.config_captive_portal_https_urls))
@@ -2621,21 +2960,21 @@
private NetworkMonitor runPortalNetworkTest() throws RemoteException {
final NetworkMonitor nm = runNetworkTest(VALIDATION_RESULT_PORTAL,
0 /* probesSucceeded */, TEST_LOGIN_URL);
- assertEquals(1, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
return nm;
}
private NetworkMonitor runNoValidationNetworkTest() throws RemoteException {
final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_VALID,
0 /* probesSucceeded */, null /* redirectUrl */);
- assertEquals(0, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
return nm;
}
private NetworkMonitor runFailedNetworkTest() throws RemoteException {
final NetworkMonitor nm = runNetworkTest(
VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
- assertEquals(0, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
return nm;
}
@@ -2643,7 +2982,7 @@
throws RemoteException {
final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_PARTIAL,
probesSucceeded, null /* redirectUrl */);
- assertEquals(0, mRegisteredReceivers.size());
+ assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
return nm;
}
@@ -2775,5 +3114,13 @@
private DataStallReportParcelable matchTcpDataStallParcelable() {
return argThat(p -> (p.detectionMethod & ConstantsShim.DETECTION_METHOD_TCP_METRICS) != 0);
}
+
+ private void assertCaptivePortalAppReceiverRegistered(boolean isPortal) {
+ // There will be configuration change receiver registered after NetworkMonitor being
+ // started. If captive portal app receiver is registered, then the size of the registered
+ // receivers will be 2. Otherwise, mRegisteredReceivers should only contain 1 configuration
+ // change receiver.
+ assertEquals(isPortal ? 2 : 1, mRegisteredReceivers.size());
+ }
}