Snap for 8426163 from 230e1fb6472342b7bdafe9b94d3387269bfdf62e to mainline-tzdata2-release

Change-Id: Ib91e72f39c3acb6e340761ff85367e02b213744f
diff --git a/Android.bp b/Android.bp
index 0f577a4..cce44b0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,6 +45,10 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
+// Whether to enable the targets in this file that target current SDKs.
+// Set to false in branches like mainline-prod where API classes are too old to build current code.
+enable_current_sdk_targets = false
+
 java_defaults {
     name: "NetworkStackDevApiLevel",
     min_sdk_version: "29",
@@ -53,14 +57,9 @@
 
 java_defaults {
     name: "NetworkStackReleaseApiLevel",
-    sdk_version: "module_31",
+    sdk_version: "system_30",
     min_sdk_version: "29",
-    target_sdk_version: "31",
-    libs: [
-        "framework-connectivity",
-        "framework-statsd",
-        "framework-wifi",
-    ]
+    target_sdk_version: "30",
 }
 
 // Libraries for the API shims
@@ -128,6 +127,7 @@
 // integer so if the next SDK release happens to use that integer, we don't need to rename them.
 java_library {
     name: "NetworkStackApi31Shims",
+    enabled: enable_current_sdk_targets,
     defaults: ["NetworkStackShimsDefaults"],
     srcs: [
         "apishim/31/**/*.java",
@@ -138,27 +138,6 @@
         "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"],
 }
@@ -168,13 +147,13 @@
 // called directly by the networkstack code.
 java_library {
     name: "NetworkStackApiCurrentShims",
+    enabled: enable_current_sdk_targets,
     defaults: ["NetworkStackShimsDefaults"],
     static_libs: [
         "NetworkStackShimsCommon",
         "NetworkStackApi29Shims",
         "NetworkStackApi30Shims",
         "NetworkStackApi31Shims",
-        "NetworkStackApi32Shims",
     ],
     sdk_version: "module_current",
     visibility: [
@@ -193,10 +172,9 @@
         "NetworkStackShimsCommon",
         "NetworkStackApi29Shims",
         "NetworkStackApi30Shims",
-        "NetworkStackApi31Shims",
     ],
     jarjar_rules: "apishim/jarjar-rules-compat.txt",
-    sdk_version: "module_31",
+    sdk_version: "system_30",
     visibility: [
         "//packages/modules/Connectivity/Tethering",
         "//packages/modules/Connectivity/tests/cts/net",
@@ -214,8 +192,8 @@
     libs: ["unsupportedappusage"],
     static_libs: [
         "androidx.annotation_annotation",
-        "modules-utils-build_system",
         "netd_aidl_interface-lateststable-java",
+        "netlink-client",
         "networkstack-client",
         "net-utils-framework-common",
         // See note on statsprotos when adding/updating proto build rules
@@ -223,7 +201,6 @@
         "statsprotos",
         "captiveportal-lib",
         "net-utils-device-common",
-        "net-utils-device-common-netlink",
     ],
     plugins: ["java_api_finder"],
 }
@@ -238,6 +215,7 @@
     ],
     static_libs: ["NetworkStackApiCurrentShims"],
     manifest: "AndroidManifestBase.xml",
+    enabled: enable_current_sdk_targets,
     visibility: [
         "//frameworks/base/tests/net/integration",
         "//packages/modules/Connectivity/Tethering/tests/integration",
@@ -279,7 +257,6 @@
     visibility: [
         "//packages/modules/NetworkStack/tests/unit",
         "//packages/modules/NetworkStack/tests/integration",
-        "//packages/modules/Connectivity/tests:__subpackages__",
         "//packages/modules/Connectivity/Tethering/tests/integration",
     ]
 }
@@ -313,10 +290,8 @@
     // 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",
-    ],
+    required: ["PlatformNetworkPermissionConfig", "PlatformCaptivePortalLogin"],
+    enabled: enable_current_sdk_targets,
 }
 
 // Pre-merge the AndroidManifest for NetworkStackNext, so that its manifest can be merged on top
@@ -324,7 +299,8 @@
     name: "NetworkStackNextManifestBase",
     defaults: ["NetworkStackAppDefaults", "NetworkStackDevApiLevel"],
     static_libs: ["NetworkStackApiCurrentLib"],
-    manifest: "AndroidManifest.xml"
+    manifest: "AndroidManifest.xml",
+    enabled: enable_current_sdk_targets,
 }
 
 // NetworkStack build targeting the current API release, for testing on in-development SDK
@@ -335,10 +311,8 @@
     certificate: "networkstack",
     manifest: "AndroidManifest_Next.xml",
     // The permission configuration *must* be included to ensure security of the device
-    required: [
-        "NetworkPermissionConfig",
-        "privapp_whitelist_com.android.networkstack",
-    ],
+    required: ["NetworkPermissionConfig"],
+    enabled: enable_current_sdk_targets,
 }
 
 // Updatable network stack for finalized API
@@ -349,10 +323,7 @@
     certificate: "networkstack",
     manifest: "AndroidManifest.xml",
     // The permission configuration *must* be included to ensure security of the device
-    required: [
-        "NetworkPermissionConfig",
-        "privapp_whitelist_com.android.networkstack",
-    ],
+    required: ["NetworkPermissionConfig"],
     updatable: true,
 }
 
@@ -429,10 +400,7 @@
     certificate: "networkstack",
     manifest: ":NetworkStackTestAndroidManifest",
     // The permission configuration *must* be included to ensure security of the device
-    required: [
-        "NetworkPermissionConfig",
-        "privapp_whitelist_com.android.networkstack",
-    ],
+    required: ["NetworkPermissionConfig"],
 }
 
 // When adding or modifying protos, the jarjar rules and possibly proguard rules need
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8750795..55357a8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,9 +19,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.android.networkstack"
   android:sharedUserId="android.uid.networkstack"
-  android:versionCode="319999900"
-  android:versionName="s_aml_319999900"
-  coreApp="true"
+  android:versionCode="309999900"
+  android:versionName="r_aml_309999900"
 >
     <!-- 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 6c64d87..2cb146a 100644
--- a/AndroidManifest_InProcess.xml
+++ b/AndroidManifest_InProcess.xml
@@ -19,8 +19,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack.inprocess"
           android:sharedUserId="android.uid.system"
-          android:process="system"
-          coreApp="true">
+          android:process="system">
     <application>
         <service android:name="com.android.server.NetworkStackService"
                  android:process="system"
diff --git a/AndroidManifest_Next.xml b/AndroidManifest_Next.xml
index 244d465..02fcb64 100644
--- a/AndroidManifest_Next.xml
+++ b/AndroidManifest_Next.xml
@@ -17,7 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
           android:sharedUserId="android.uid.networkstack"
-          android:versionCode="320000000"
-          android:versionName="T-next"
-          coreApp="true">
+          android:versionCode="300000000"
+          android:versionName="R-next">
 </manifest>
diff --git a/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java
index 07327be..2ac25af 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/ConnectivityManagerShimImpl.java
@@ -16,14 +16,8 @@
 
 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;
 
@@ -36,10 +30,7 @@
  * 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);
-    }
+    protected ConnectivityManagerShimImpl(Context context) {}
 
     /**
      * Get a new instance of {@link ConnectivityManagerShim}.
@@ -61,31 +52,12 @@
 
     /**
      * See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback
+     * @throws UnsupportedApiLevelException if API is not available in this API level.
      */
     @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);
+            @NonNull Handler handler) throws UnsupportedApiLevelException {
+        // Not supported for API 29.
+        throw new UnsupportedApiLevelException("Not supported in API 29.");
     }
 }
diff --git a/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java
index 7c1d786..97f1f60 100644
--- a/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java
+++ b/apishim/30/com/android/networkstack/apishim/api30/ConnectivityManagerShimImpl.java
@@ -16,10 +16,10 @@
 
 package com.android.networkstack.apishim.api30;
 
-import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
-
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
+import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.os.Build;
 import android.os.Handler;
@@ -28,24 +28,25 @@
 import androidx.annotation.RequiresApi;
 
 import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+import com.android.networkstack.apishim.common.ShimUtils;
 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 final ConnectivityManager mCm;
     protected ConnectivityManagerShimImpl(Context context) {
         super(context);
+        mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     /**
      * Get a new instance of {@link ConnectivityManagerShim}.
      */
-    @RequiresApi(Build.VERSION_CODES.Q)
     public static ConnectivityManagerShim newInstance(Context context) {
-        if (!isAtLeastR()) {
+        if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) {
             return com.android.networkstack.apishim.api29.ConnectivityManagerShimImpl
                     .newInstance(context);
         }
@@ -64,9 +65,27 @@
         throw new UnsupportedApiLevelException("Not supported in API 30.");
     }
 
-    @NonNull
+    /**
+     * See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback
+     * @throws UnsupportedApiLevelException if API is not available in this API level.
+     */
     @Override
-    protected NetworkRequest.Builder makeEmptyCapabilitiesRequest() {
-        return new NetworkRequest.Builder().clearCapabilities();
+    @RequiresApi(Build.VERSION_CODES.R)
+    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 = new NetworkRequest.Builder()
+                .clearCapabilities()
+                .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);
     }
 }
diff --git a/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java b/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
similarity index 98%
rename from apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
index 5ae006b..5af7412 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import android.net.CaptivePortalData;
 import android.net.Uri;
diff --git a/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java b/apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
similarity index 98%
rename from apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
index 46de698..0e01c98 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
 
diff --git a/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java b/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
similarity index 96%
rename from apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
rename to apishim/31/com/android/networkstack/apishim/ConstantsShim.java
index 95ff072..0184845 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
+++ b/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import androidx.annotation.VisibleForTesting;
 
diff --git a/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java b/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
similarity index 94%
rename from apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
index a5c9a71..d2615e6 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import android.net.LinkProperties;
 import android.net.NetworkCapabilities;
@@ -50,7 +50,7 @@
         if (!useApiAboveR()) {
             return com.android.networkstack.apishim.api30.NetworkInformationShimImpl.newInstance();
         }
-        return new NetworkInformationShimImpl();
+        return new com.android.networkstack.apishim.NetworkInformationShimImpl();
     }
 
     @Nullable
diff --git a/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java b/apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java
similarity index 87%
rename from apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java
index 2dc5d72..ccc8f70 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
 
@@ -58,13 +58,6 @@
     }
 
     @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/api31/NetworkShimImpl.java b/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
similarity index 95%
rename from apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
index eda8e27..0c92391 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import android.net.Network;
 
diff --git a/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java b/apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java
similarity index 87%
rename from apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java
index 1b5cbae..e15872f 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 import android.content.Context;
 import android.os.Build;
@@ -48,7 +48,9 @@
     public boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
             @NonNull String callingPackage, @Nullable String callingAttributionTag,
             boolean throwException) {
+        // Since checkAndNoteWriteSettingsOperation with callingAttributionTag (S method) is not
+        // available in AOSP, calling R method (same as API 30 shim) temporary.
         return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
-                callingAttributionTag, throwException);
+                throwException);
     }
 }
diff --git a/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java b/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
similarity index 94%
rename from apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
index f5aa80b..483bde0 100644
--- a/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.networkstack.apishim.api31;
+package com.android.networkstack.apishim;
 
 /**
  * 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
deleted file mode 100644
index 2056b1b..0000000
--- a/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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
deleted file mode 100644
index a7aa0c8..0000000
--- a/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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/32/com/android/networkstack/apishim/ConstantsShim.java b/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
deleted file mode 100644
index 0a5b555..0000000
--- a/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.networkstack.apishim;
-
-import androidx.annotation.VisibleForTesting;
-
-/**
- * Utility class for defining and importing constants from the Android platform.
- */
-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.
-     * This should only be used by test code. Production code that uses the shims should be using
-     * the shimmed objects and methods themselves.
-     */
-    @VisibleForTesting
-    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
deleted file mode 100644
index 28aa75c..0000000
--- a/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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
deleted file mode 100644
index 95ae5ba..0000000
--- a/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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/32/com/android/networkstack/apishim/NetworkShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
deleted file mode 100644
index 2e31a78..0000000
--- a/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.networkstack.apishim;
-
-import android.net.Network;
-import android.os.Build;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-
-/**
- * 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 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
deleted file mode 100644
index 46d2102..0000000
--- a/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
deleted file mode 100644
index 2f4e500..0000000
--- a/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.networkstack.apishim;
-
-import android.os.Build;
-
-import androidx.annotation.RequiresApi;
-
-/**
- * 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 31 shim, so inherit everything from that.
-    protected SocketUtilsShimImpl() {}
-}
diff --git a/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java b/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java
index 86d785e..67b3df7 100644
--- a/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/ConnectivityManagerShim.java
@@ -42,7 +42,8 @@
 
     /** See android.net.ConnectivityManager#registerSystemDefaultNetworkCallback */
     void registerSystemDefaultNetworkCallback(
-            @NonNull NetworkCallback networkCallback, @NonNull Handler handler);
+            @NonNull NetworkCallback networkCallback, @NonNull Handler handler)
+            throws UnsupportedApiLevelException;
 
     /** See android.net.ConnectivityManager#registerDefaultNetworkCallbackForUid */
     default void registerDefaultNetworkCallbackForUid(
diff --git a/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
index d07d1ae..7d6d7bf 100644
--- a/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
@@ -37,14 +37,6 @@
             @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.
      */
diff --git a/apishim/jarjar-rules-compat.txt b/apishim/jarjar-rules-compat.txt
index 4f34ccb..dba2b49 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 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
+# 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
diff --git a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
index 8b388ad..2ba1dcc 100755
--- a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
+++ b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -103,22 +103,11 @@
     }
 
     public boolean isSuccessful() {
-        return isSuccessCode(mHttpResponseCode);
+        return mHttpResponseCode == SUCCESS_CODE;
     }
 
     public boolean isPortal() {
-        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);
+        return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
     }
 
     public boolean isFailed() {
diff --git a/common/moduleutils/Android.bp b/common/moduleutils/Android.bp
index d90c33d..5d1c9e3 100644
--- a/common/moduleutils/Android.bp
+++ b/common/moduleutils/Android.bp
@@ -21,14 +21,21 @@
     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",
@@ -36,19 +43,6 @@
 }
 
 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: [
@@ -64,6 +58,7 @@
         "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 43005cd..9189002 100644
--- a/common/moduleutils/src/android/net/ip/ConntrackMonitor.java
+++ b/common/moduleutils/src/android/net/ip/ConntrackMonitor.java
@@ -16,9 +16,12 @@
 
 package android.net.ip;
 
-import static com.android.net.module.util.netlink.ConntrackMessage.DYING_MASK;
-import static com.android.net.module.util.netlink.ConntrackMessage.ESTABLISHED_MASK;
+import static android.net.netlink.ConntrackMessage.DYING_MASK;
+import static android.net.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;
@@ -26,9 +29,6 @@
 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,12 +51,6 @@
     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.
      */
@@ -182,7 +176,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, SOCKET_RECV_BUFSIZE);
+                | NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY);
         mConsumer = cb;
     }
 
diff --git a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
index a16fdf2..b45c061 100644
--- a/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
+++ b/common/moduleutils/src/android/net/ip/IpNeighborMonitor.java
@@ -16,24 +16,22 @@
 
 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 17157d8..3d314f1 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,9 +35,6 @@
 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;
@@ -59,13 +56,9 @@
     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.
      *
@@ -75,23 +68,14 @@
      * @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 sockRcvbufSize) {
+            int family, int bindGroups) {
         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
@@ -100,9 +84,6 @@
 
         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/networkstackclient/src/android/net/shared/InitialConfiguration.java b/common/moduleutils/src/android/net/shared/InitialConfiguration.java
similarity index 100%
rename from common/networkstackclient/src/android/net/shared/InitialConfiguration.java
rename to common/moduleutils/src/android/net/shared/InitialConfiguration.java
diff --git a/common/networkstackclient/src/android/net/shared/Layer2Information.java b/common/moduleutils/src/android/net/shared/Layer2Information.java
similarity index 100%
rename from common/networkstackclient/src/android/net/shared/Layer2Information.java
rename to common/moduleutils/src/android/net/shared/Layer2Information.java
diff --git a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
index b151cb9..981a576 100644
--- a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
+++ b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
@@ -19,7 +19,6 @@
 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;
@@ -28,8 +27,6 @@
 
 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
@@ -39,14 +36,6 @@
     // 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";
@@ -70,19 +59,18 @@
     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)
-                && (isVcnManaged || isOemPaid || isDefaultCapable)) {
+                && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+                && nc.hasCapability(NET_CAPABILITY_TRUSTED)) {
+            // Real networks
             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/networkstackclient/src/android/net/shared/ParcelableUtil.java b/common/moduleutils/src/android/net/shared/ParcelableUtil.java
similarity index 100%
rename from common/networkstackclient/src/android/net/shared/ParcelableUtil.java
rename to common/moduleutils/src/android/net/shared/ParcelableUtil.java
diff --git a/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java b/common/moduleutils/src/android/net/shared/PrivateDnsConfig.java
similarity index 100%
rename from common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
rename to common/moduleutils/src/android/net/shared/PrivateDnsConfig.java
diff --git a/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java b/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
similarity index 81%
rename from common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
rename to common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
index 3bf6744..d3bc04d 100644
--- a/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
+++ b/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
@@ -16,17 +16,12 @@
 
 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;
@@ -37,8 +32,6 @@
 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;
@@ -83,17 +76,6 @@
     // 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}.
      */
@@ -104,7 +86,7 @@
          * Specify that the configuration should not enable IPv4. It is enabled by default.
          */
         public Builder withoutIPv4() {
-            mConfig.mIPv4ProvisioningMode = PROV_IPV4_DISABLED;
+            mConfig.mEnableIPv4 = false;
             return this;
         }
 
@@ -112,7 +94,7 @@
          * Specify that the configuration should not enable IPv6. It is enabled by default.
          */
         public Builder withoutIPv6() {
-            mConfig.mIPv6ProvisioningMode = PROV_IPV6_DISABLED;
+            mConfig.mEnableIPv6 = false;
             return this;
         }
 
@@ -174,7 +156,6 @@
          * Specify a static configuration for provisioning.
          */
         public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) {
-            mConfig.mIPv4ProvisioningMode = PROV_IPV4_STATIC;
             mConfig.mStaticIpConfig = staticConfig;
             return this;
         }
@@ -199,7 +180,7 @@
          * Specify that IPv6 address generation should use a random MAC address.
          */
         public Builder withRandomMacAddress() {
-            mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_EUI64;
+            mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
             return this;
         }
 
@@ -207,7 +188,7 @@
          * Specify that IPv6 address generation should use a stable MAC address.
          */
         public Builder withStableMacAddress() {
-            mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+            mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
             return this;
         }
 
@@ -252,32 +233,15 @@
          *
          * @param: options customized DHCP option stable parcelable list.
          */
-        public Builder withDhcpOptions(@Nullable List<DhcpOption> options) {
+        public Builder withDhcpOptions(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);
         }
     }
@@ -463,6 +427,8 @@
         }
     }
 
+    public boolean mEnableIPv4 = true;
+    public boolean mEnableIPv6 = true;
     public boolean mEnablePreconnection = false;
     public boolean mUsingMultinetworkPolicyTracker = true;
     public boolean mUsingIpReachabilityMonitor = true;
@@ -471,18 +437,18 @@
     public StaticIpConfiguration mStaticIpConfig;
     public ApfCapabilities mApfCapabilities;
     public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
-    public int mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+    public int mIPv6AddrGenMode = INetd.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;
@@ -499,8 +465,6 @@
         mScanResultInfo = other.mScanResultInfo;
         mLayer2Info = other.mLayer2Info;
         mDhcpOptions = other.mDhcpOptions;
-        mIPv4ProvisioningMode = other.mIPv4ProvisioningMode;
-        mIPv6ProvisioningMode = other.mIPv6ProvisioningMode;
     }
 
     /**
@@ -508,10 +472,8 @@
      */
     public ProvisioningConfigurationParcelable toStableParcelable() {
         final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable();
-        p.enableIPv4 = (mIPv4ProvisioningMode != PROV_IPV4_DISABLED);
-        p.ipv4ProvisioningMode = mIPv4ProvisioningMode;
-        p.enableIPv6 = (mIPv6ProvisioningMode != PROV_IPV6_DISABLED);
-        p.ipv6ProvisioningMode = mIPv6ProvisioningMode;
+        p.enableIPv4 = mEnableIPv4;
+        p.enableIPv6 = mEnableIPv6;
         p.enablePreconnection = mEnablePreconnection;
         p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker;
         p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor;
@@ -533,16 +495,13 @@
 
     /**
      * 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, int interfaceVersion) {
+            @Nullable ProvisioningConfigurationParcelable p) {
         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;
@@ -559,49 +518,14 @@
         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)
@@ -616,8 +540,6 @@
                 .add("mScanResultInfo: " + mScanResultInfo)
                 .add("mLayer2Info: " + mLayer2Info)
                 .add("mDhcpOptions: " + mDhcpOptions)
-                .add("mIPv4ProvisioningMode: " + ipv4ProvisioningMode)
-                .add("mIPv6ProvisioningMode: " + ipv6ProvisioningMode)
                 .toString();
     }
 
@@ -647,7 +569,9 @@
     public boolean equals(Object obj) {
         if (!(obj instanceof ProvisioningConfiguration)) return false;
         final ProvisioningConfiguration other = (ProvisioningConfiguration) obj;
-        return mEnablePreconnection == other.mEnablePreconnection
+        return mEnableIPv4 == other.mEnableIPv4
+                && mEnableIPv6 == other.mEnableIPv6
+                && mEnablePreconnection == other.mEnablePreconnection
                 && mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker
                 && mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor
                 && mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs
@@ -660,9 +584,7 @@
                 && Objects.equals(mDisplayName, other.mDisplayName)
                 && Objects.equals(mScanResultInfo, other.mScanResultInfo)
                 && Objects.equals(mLayer2Info, other.mLayer2Info)
-                && dhcpOptionListEquals(mDhcpOptions, other.mDhcpOptions)
-                && mIPv4ProvisioningMode == other.mIPv4ProvisioningMode
-                && mIPv6ProvisioningMode == other.mIPv6ProvisioningMode;
+                && dhcpOptionListEquals(mDhcpOptions, other.mDhcpOptions);
     }
 
     public boolean isValid() {
diff --git a/common/netlinkclient/Android.bp b/common/netlinkclient/Android.bp
new file mode 100644
index 0000000..9a60e57
--- /dev/null
+++ b/common/netlinkclient/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+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
new file mode 100644
index 0000000..cc8bb7e
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/ConntrackMessage.java
@@ -0,0 +1,552 @@
+/*
+ * 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: &lt;linux_src&gt;/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
new file mode 100644
index 0000000..c085123
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/InetDiagMessage.java
@@ -0,0 +1,222 @@
+/*
+ * 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: &lt;linux_src&gt;/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 &lt;linux_src&gt;/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/netdev@vger.kernel.org/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
new file mode 100644
index 0000000..ab9d2e6
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NdOption.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 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
new file mode 100644
index 0000000..7b976f1
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NduseroptMessage.java
@@ -0,0 +1,141 @@
+/*
+ * 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
new file mode 100644
index 0000000..b4d9cc0
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NetlinkConstants.java
@@ -0,0 +1,242 @@
+/*
+ * 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
new file mode 100644
index 0000000..36b02c6
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NetlinkErrorMessage.java
@@ -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 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
new file mode 100644
index 0000000..ab2c223
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NetlinkMessage.java
@@ -0,0 +1,153 @@
+/*
+ * 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
new file mode 100644
index 0000000..ab4c052
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/NetlinkSocket.java
@@ -0,0 +1,158 @@
+/*
+ * 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
new file mode 100644
index 0000000..099ff07
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/RtNetlinkNeighborMessage.java
@@ -0,0 +1,229 @@
+/*
+ * 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: &lt;linux_src&gt;/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
new file mode 100644
index 0000000..5772a94
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructInetDiagMsg.java
@@ -0,0 +1,59 @@
+/*
+ * 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 &lt;linux_src&gt;/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
new file mode 100644
index 0000000..520f0ef
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructInetDiagReqV2.java
@@ -0,0 +1,97 @@
+/*
+ * 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 &lt;linux_src&gt;/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
new file mode 100644
index 0000000..2e9fa25
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructInetDiagSockId.java
@@ -0,0 +1,86 @@
+/*
+ * 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 &lt;linux_src&gt;/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
new file mode 100644
index 0000000..64364df
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNdMsg.java
@@ -0,0 +1,165 @@
+/*
+ * 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: &lt;linux_src&gt;/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
new file mode 100644
index 0000000..607aaba
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNdOptPref64.java
@@ -0,0 +1,169 @@
+/*
+ * 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
new file mode 100644
index 0000000..16cf563
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNdaCacheInfo.java
@@ -0,0 +1,117 @@
+/*
+ * 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: &lt;linux_src&gt;/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
new file mode 100644
index 0000000..7f247f5
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNfGenMsg.java
@@ -0,0 +1,103 @@
+/*
+ * 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 &lt;linux_src&gt;/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
new file mode 100644
index 0000000..b6e1d3f
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
@@ -0,0 +1,284 @@
+/*
+ * 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: &lt;linux_src&gt;/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
new file mode 100644
index 0000000..9ea4364
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNlMsgErr.java
@@ -0,0 +1,68 @@
+/*
+ * 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 &lt;linux_src&gt;/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
new file mode 100644
index 0000000..55a649d
--- /dev/null
+++ b/common/netlinkclient/src/android/net/netlink/StructNlMsgHdr.java
@@ -0,0 +1,158 @@
+/*
+ * 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 &lt;linux_src&gt;/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 c344d07..96ff315 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -72,7 +72,7 @@
         // For framework parcelables.
         "frameworks/base/core/java",
         // For API parcelables in connectivity
-        "packages/modules/Connectivity/framework/aidl-export",
+        "frameworks/base/packages/Connectivity/framework/aidl-export",
         "frameworks/native/aidl/binder", // For PersistableBundle.aidl
     ],
     srcs: [
@@ -121,7 +121,7 @@
             enabled: false,
         },
     },
-    imports: ["ipmemorystore-aidl-interfaces-V10"],
+    imports: ["ipmemorystore-aidl-interfaces"],
     versions: [
         "1",
         "2",
@@ -133,8 +133,6 @@
         "8",
         "9",
         "10",
-        "11",
-        "12",
     ],
     // TODO: have tethering depend on networkstack-client and set visibility to private
     visibility: [
@@ -147,34 +145,25 @@
 java_library {
     name: "networkstack-client",
     sdk_version: "system_current",
-    // this is part of updatable modules(NetworkStack) which runs on Q and above
+    // this is part of updatable modules(NetworkStack) which targets 29(Q)
     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-V10-java",
-        "networkstack-aidl-interfaces-V12-java",
+        "networkstack-aidl-interfaces-V10-java",
     ],
     visibility: [
-        "//frameworks/base/packages/Connectivity/service",
+        "//frameworks/base/packages/Tethering",
         "//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: [
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 048e84c..bf7a26d 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 7dbbc98..2024391 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 4300c83..8a1b57e 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 3a263e2..e711272 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 c663ccf..4abecb9 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 3740e15..05c48b3 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 9d87fbb..0bc8c5e 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 1e6a41c..cf30fa1 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 dccdf27..e71de47 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 227785d..2ac7644 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 377a3ec..42a1feb 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 59b96cd..1bea082 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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 c01564b..e2ecbb4 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,30 +1,14 @@
-/*
- * 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`.
+// 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.
 //
-// You must not make a backward incompatible change to any AIDL file built
+// You must not make a backward incompatible changes to the AIDL files 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
deleted file mode 100644
index 2914d2a..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/.hash
+++ /dev/null
@@ -1 +0,0 @@
-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
deleted file mode 100644
index 771deda..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DataStallReportParcelable.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 31f2194..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/DhcpResultsParcelable.aidl
+++ /dev/null
@@ -1,44 +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 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
deleted file mode 100644
index d92196d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitor.aidl
+++ /dev/null
@@ -1,59 +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 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
deleted file mode 100644
index 36eda8e..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkMonitorCallbacks.aidl
+++ /dev/null
@@ -1,46 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 8120ffc..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackConnector.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 0b6b778..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/INetworkStackStatusCallback.aidl
+++ /dev/null
@@ -1,38 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 6103774..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InformationElementParcelable.aidl
+++ /dev/null
@@ -1,39 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 6a597e6..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/InitialConfigurationParcelable.aidl
+++ /dev/null
@@ -1,41 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 83796ee..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2InformationParcelable.aidl
+++ /dev/null
@@ -1,40 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 4b3fff5..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/Layer2PacketParcelable.aidl
+++ /dev/null
@@ -1,39 +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 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
deleted file mode 100644
index 18cf954..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NattKeepalivePacketDataParcelable.aidl
+++ /dev/null
@@ -1,41 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 4d6d5a2..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/NetworkTestResultParcelable.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 1457caf..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/PrivateDnsConfigParcel.aidl
+++ /dev/null
@@ -1,39 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 0b7a7a1..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ProvisioningConfigurationParcelable.aidl
+++ /dev/null
@@ -1,54 +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.
-*/
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 94fc27f..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ScanResultInfoParcelable.aidl
+++ /dev/null
@@ -1,40 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 0e1c21c..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/TcpKeepalivePacketDataParcelable.aidl
+++ /dev/null
@@ -1,47 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 3cd8860..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpLeaseParcelable.aidl
+++ /dev/null
@@ -1,43 +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 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
deleted file mode 100644
index fa412cb..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/DhcpServingParamsParcel.aidl
+++ /dev/null
@@ -1,48 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 9312f47..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpEventCallbacks.aidl
+++ /dev/null
@@ -1,38 +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 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
deleted file mode 100644
index 1109f35..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServer.aidl
+++ /dev/null
@@ -1,45 +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 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
deleted file mode 100644
index ab8577c..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/dhcp/IDhcpServerCallbacks.aidl
+++ /dev/null
@@ -1,38 +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 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
deleted file mode 100644
index 1fe4c4c..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClient.aidl
+++ /dev/null
@@ -1,52 +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 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
deleted file mode 100644
index 488510d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/ip/IIpClientCallbacks.aidl
+++ /dev/null
@@ -1,51 +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 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
deleted file mode 100644
index eea3e0d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/11/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
+++ /dev/null
@@ -1,39 +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 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
deleted file mode 100644
index e96fe34..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/.hash
+++ /dev/null
@@ -1 +0,0 @@
-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
deleted file mode 100644
index 771deda..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DataStallReportParcelable.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 31f2194..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/DhcpResultsParcelable.aidl
+++ /dev/null
@@ -1,44 +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 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
deleted file mode 100644
index d92196d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitor.aidl
+++ /dev/null
@@ -1,59 +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 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
deleted file mode 100644
index 36eda8e..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkMonitorCallbacks.aidl
+++ /dev/null
@@ -1,46 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 8120ffc..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackConnector.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 0b6b778..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/INetworkStackStatusCallback.aidl
+++ /dev/null
@@ -1,38 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 6103774..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InformationElementParcelable.aidl
+++ /dev/null
@@ -1,39 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 6a597e6..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/InitialConfigurationParcelable.aidl
+++ /dev/null
@@ -1,41 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 83796ee..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2InformationParcelable.aidl
+++ /dev/null
@@ -1,40 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 4b3fff5..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/Layer2PacketParcelable.aidl
+++ /dev/null
@@ -1,39 +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 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
deleted file mode 100644
index 18cf954..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NattKeepalivePacketDataParcelable.aidl
+++ /dev/null
@@ -1,41 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 4d6d5a2..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/NetworkTestResultParcelable.aidl
+++ /dev/null
@@ -1,42 +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 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
deleted file mode 100644
index 1457caf..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/PrivateDnsConfigParcel.aidl
+++ /dev/null
@@ -1,39 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 9ecd110..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ProvisioningConfigurationParcelable.aidl
+++ /dev/null
@@ -1,62 +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.
-*/
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 94fc27f..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ScanResultInfoParcelable.aidl
+++ /dev/null
@@ -1,40 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 0e1c21c..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/TcpKeepalivePacketDataParcelable.aidl
+++ /dev/null
@@ -1,47 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 3cd8860..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpLeaseParcelable.aidl
+++ /dev/null
@@ -1,43 +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 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
deleted file mode 100644
index fa412cb..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/DhcpServingParamsParcel.aidl
+++ /dev/null
@@ -1,48 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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
deleted file mode 100644
index 9312f47..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpEventCallbacks.aidl
+++ /dev/null
@@ -1,38 +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 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
deleted file mode 100644
index 1109f35..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServer.aidl
+++ /dev/null
@@ -1,45 +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 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
deleted file mode 100644
index ab8577c..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/dhcp/IDhcpServerCallbacks.aidl
+++ /dev/null
@@ -1,38 +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 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
deleted file mode 100644
index a97511e..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClient.aidl
+++ /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 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
deleted file mode 100644
index 488510d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/ip/IIpClientCallbacks.aidl
+++ /dev/null
@@ -1,51 +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 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
deleted file mode 100644
index eea3e0d..0000000
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/12/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
+++ /dev/null
@@ -1,39 +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 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 771deda..0f860a5 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,18 +1,3 @@
-/**
- * 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 31f2194..4445be7 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,18 +1,3 @@
-/**
- * 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 d92196d..db9145f 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,18 +1,3 @@
-/**
- * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -50,7 +35,6 @@
   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 36eda8e..b2685ad 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,18 +1,3 @@
-/*
- * 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 8120ffc..396b42a 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,18 +1,3 @@
-/**
- * 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 0b6b778..97c9970 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,18 +1,3 @@
-/*
- * 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 6103774..77fca83 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,18 +1,3 @@
-/*
- * 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 6a597e6..6137305 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,18 +1,3 @@
-/*
- * 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 83796ee..d3adbb3 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,18 +1,3 @@
-/*
- * 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 4b3fff5..b45f6da 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,18 +1,3 @@
-/**
- * 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 18cf954..7634ac9 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,18 +1,3 @@
-/*
- * 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 4d6d5a2..1d0bbbe 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,18 +1,3 @@
-/**
- * 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 1457caf..c6d6361 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,18 +1,3 @@
-/*
- * 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 9ecd110..171817c 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,19 +1,3 @@
-/*
-**
-** 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -35,13 +19,7 @@
 package android.net;
 @JavaDerive(toString=true)
 parcelable ProvisioningConfigurationParcelable {
-  /**
-   * @deprecated use ipv4ProvisioningMode instead.
-   */
   boolean enableIPv4;
-  /**
-   * @deprecated use ipv6ProvisioningMode instead.
-   */
   boolean enableIPv6;
   boolean usingMultinetworkPolicyTracker;
   boolean usingIpReachabilityMonitor;
@@ -57,6 +35,4 @@
   @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 94fc27f..4646ede 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,18 +1,3 @@
-/*
- * 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 0e1c21c..00f15da 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,18 +1,3 @@
-/*
- * 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 3cd8860..b0a0f0f 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,18 +1,3 @@
-/**
- * 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 fa412cb..d56ef8e 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,19 +1,3 @@
-/**
- *
- * 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 9312f47..8f3288e 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,18 +1,3 @@
-/**
- * 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 1109f35..83cebdf 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,18 +1,3 @@
-/**
- * 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 ab8577c..35da06c 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,18 +1,3 @@
-/**
- * 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 a97511e..5607b2a 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,18 +1,3 @@
-/**
- * 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.                          //
 ///////////////////////////////////////////////////////////////////////////////
@@ -49,10 +34,4 @@
   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 488510d..9a84784 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,18 +1,3 @@
-/**
- * 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 eea3e0d..c97212b 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,18 +1,3 @@
-/**
- * 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 b124734..3fc81a3 100644
--- a/common/networkstackclient/src/android/net/INetworkMonitor.aidl
+++ b/common/networkstackclient/src/android/net/INetworkMonitor.aidl
@@ -44,16 +44,10 @@
     // 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. 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.
+    // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. 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
deleted file mode 100644
index f2c1d35..0000000
--- a/common/networkstackclient/src/android/net/IpMemoryStore.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.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
deleted file mode 100644
index 0f66981..0000000
--- a/common/networkstackclient/src/android/net/NetworkMonitorManager.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.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 54a5729..0aeebcb 100644
--- a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
+++ b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
@@ -29,9 +29,7 @@
 
 @JavaDerive(toString=true)
 parcelable ProvisioningConfigurationParcelable {
-    /** @deprecated use ipv4ProvisioningMode instead. */
     boolean enableIPv4;
-    /** @deprecated use ipv6ProvisioningMode instead. */
     boolean enableIPv6;
     boolean usingMultinetworkPolicyTracker;
     boolean usingIpReachabilityMonitor;
@@ -47,6 +45,4 @@
     @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 f76a230..029bdb3 100644
--- a/common/networkstackclient/src/android/net/ip/IIpClient.aidl
+++ b/common/networkstackclient/src/android/net/ip/IIpClient.aidl
@@ -23,36 +23,6 @@
 
 /** @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
deleted file mode 100644
index b17fcaa..0000000
--- a/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
+++ /dev/null
@@ -1,136 +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.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
deleted file mode 100644
index b45405f..0000000
--- a/common/networkstackclient/src/android/net/ip/IpClientManager.java
+++ /dev/null
@@ -1,326 +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.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
deleted file mode 100644
index 1b55776..0000000
--- a/common/networkstackclient/src/android/net/ip/IpClientUtil.java
+++ /dev/null
@@ -1,204 +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.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/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java b/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
deleted file mode 100644
index 5666985..0000000
--- a/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
+++ /dev/null
@@ -1,223 +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.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/lint-baseline-current-lib.xml b/lint-baseline-current-lib.xml
index e8cfe3e..f7b00f2 100644
--- a/lint-baseline-current-lib.xml
+++ b/lint-baseline-current-lib.xml
@@ -3,6 +3,83 @@
 
     <issue
         id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1032"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1034"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1087"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1089"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#any`"
+        errorLine1="        final boolean haveKeepaliveResponses = CollectionUtils.any(mKeepalivePackets,"
+        errorLine2="                                                               ~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1368"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toIntArray`"
+        errorLine1="                    CollectionUtils.toIntArray(mDnsReturnCode),"
+        errorLine2="                                    ~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
+            line="302"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toLongArray`"
+        errorLine1="                    CollectionUtils.toLongArray(mDnsTimeStamp),"
+        errorLine2="                                    ~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
+            line="303"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
         message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
         errorLine1="        newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
         errorLine2="                                                   ~~~~~~~~~~~~~~">
@@ -25,6 +102,50 @@
 
     <issue
         id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="            mStatsBuilder.setIpv4LatencyMicros(ConnectivityUtils.saturatedCast(mIpv4Watch.stop()));"
+        errorLine2="                                                                 ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
+            line="74"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="            mStatsBuilder.setIpv6LatencyMicros(ConnectivityUtils.saturatedCast(mIpv6Watch.stop()));"
+        errorLine2="                                                                 ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
+            line="83"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#isEmpty`"
+        errorLine1="        if (isEmpty(mCaptivePortalFallbackSpecs)) {"
+        errorLine2="            ~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+            line="2279"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#isIPv6ULA`"
+        errorLine1="                    || isIPv6ULA(address)) {"
+        errorLine2="                       ~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+            line="2447"
+            column="24"/>
+    </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="                                             ~~~~~~~~~~~~~~~">
@@ -34,4 +155,48 @@
             column="46"/>
     </issue>
 
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="        int latencyUs = ConnectivityUtils.saturatedCast(durationUs);"
+        errorLine2="                                          ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="198"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="                .setRemainingTtlSecs(ConnectivityUtils.saturatedCast(secondsRemaining))"
+        errorLine2="                                                       ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="209"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="                        ConnectivityUtils.saturatedCast(capportData.getByteLimit() / 1000))"
+        errorLine2="                                          ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="212"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="        mStatsBuilder.setLatencyMicros(ConnectivityUtils.saturatedCast(mWatch.stop()));"
+        errorLine2="                                                         ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="237"
+            column="58"/>
+    </issue>
+
 </issues>
diff --git a/lint-baseline-stable-lib.xml b/lint-baseline-stable-lib.xml
index e8cfe3e..f7b00f2 100644
--- a/lint-baseline-stable-lib.xml
+++ b/lint-baseline-stable-lib.xml
@@ -3,6 +3,83 @@
 
     <issue
         id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1032"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1034"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1087"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
+        errorLine1="                        ConnectivityUtils.addressAndPortToString("
+        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1089"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#any`"
+        errorLine1="        final boolean haveKeepaliveResponses = CollectionUtils.any(mKeepalivePackets,"
+        errorLine2="                                                               ~~~">
+        <location
+            file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
+            line="1368"
+            column="64"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toIntArray`"
+        errorLine1="                    CollectionUtils.toIntArray(mDnsReturnCode),"
+        errorLine2="                                    ~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
+            line="302"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toLongArray`"
+        errorLine1="                    CollectionUtils.toLongArray(mDnsTimeStamp),"
+        errorLine2="                                    ~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
+            line="303"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
         message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
         errorLine1="        newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
         errorLine2="                                                   ~~~~~~~~~~~~~~">
@@ -25,6 +102,50 @@
 
     <issue
         id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="            mStatsBuilder.setIpv4LatencyMicros(ConnectivityUtils.saturatedCast(mIpv4Watch.stop()));"
+        errorLine2="                                                                 ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
+            line="74"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="            mStatsBuilder.setIpv6LatencyMicros(ConnectivityUtils.saturatedCast(mIpv6Watch.stop()));"
+        errorLine2="                                                                 ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
+            line="83"
+            column="66"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#isEmpty`"
+        errorLine1="        if (isEmpty(mCaptivePortalFallbackSpecs)) {"
+        errorLine2="            ~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+            line="2279"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#isIPv6ULA`"
+        errorLine1="                    || isIPv6ULA(address)) {"
+        errorLine2="                       ~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
+            line="2447"
+            column="24"/>
+    </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="                                             ~~~~~~~~~~~~~~~">
@@ -34,4 +155,48 @@
             column="46"/>
     </issue>
 
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="        int latencyUs = ConnectivityUtils.saturatedCast(durationUs);"
+        errorLine2="                                          ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="198"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="                .setRemainingTtlSecs(ConnectivityUtils.saturatedCast(secondsRemaining))"
+        errorLine2="                                                       ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="209"
+            column="56"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="                        ConnectivityUtils.saturatedCast(capportData.getByteLimit() / 1000))"
+        errorLine2="                                          ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="212"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
+        errorLine1="        mStatsBuilder.setLatencyMicros(ConnectivityUtils.saturatedCast(mWatch.stop()));"
+        errorLine2="                                                         ~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
+            line="237"
+            column="58"/>
+    </issue>
+
 </issues>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 706f174..e54f11c 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 lokationen"</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="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/config.xml b/res/values/config.xml
index 805ca04..d6a11ab 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -105,20 +105,4 @@
          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 bfb450e..b2967b9 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -77,13 +77,6 @@
             <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 7a13392..34469b8 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -1411,7 +1411,7 @@
         //     pass
         // if it's ICMPv6 RS to any:
         //   drop
-        // if it's ICMPv6 NA to anything in ff02::/120
+        // if it's ICMPv6 NA to ff02::1 or ff02::2:
         //   drop
         // if keepalive ack
         //   drop
@@ -1495,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 anything in ff02::/120.
+     * <li>Drop IPv6 ICMPv6 NAs to ff02::1 or ff02::2.
      * <li>Drop IPv6 ICMPv6 RSs.
      * <li>Filter IPv4 packets (see generateIPv4FilterLocked())
      * <li>Filter IPv6 packets (see generateIPv6FilterLocked())
diff --git a/src/android/net/dhcp/DhcpPacket.java b/src/android/net/dhcp/DhcpPacket.java
index 76dc807..1331a24 100644
--- a/src/android/net/dhcp/DhcpPacket.java
+++ b/src/android/net/dhcp/DhcpPacket.java
@@ -403,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 sTestOverrideVendorId = null;
+    static String testOverrideVendorId = null;
 
     protected DhcpPacket(int transId, short secs, Inet4Address clientIp, Inet4Address yourIp,
                          Inet4Address nextIp, Inet4Address relayIp,
@@ -779,7 +779,7 @@
      * with the customized option value if any.
      */
     private static String getVendorId(@Nullable List<DhcpOption> customizedClientOptions) {
-        if (sTestOverrideVendorId != null) return sTestOverrideVendorId;
+        if (testOverrideVendorId != null) return testOverrideVendorId;
 
         String vendorId = "android-dhcp-" + Build.VERSION.RELEASE;
         if (customizedClientOptions != null) {
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 12ab3fd..b03d653 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -18,9 +18,6 @@
 
 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;
@@ -39,7 +36,6 @@
 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;
@@ -64,7 +60,6 @@
 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;
@@ -73,7 +68,6 @@
 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;
@@ -100,7 +94,6 @@
 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;
@@ -152,7 +145,6 @@
  * @hide
  */
 public class IpClient extends StateMachine {
-    private static final String TAG = IpClient.class.getSimpleName();
     private static final boolean DBG = false;
 
     // For message logging.
@@ -400,24 +392,6 @@
                 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";
@@ -618,33 +592,11 @@
             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)
          */
@@ -653,16 +605,6 @@
             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,
@@ -715,7 +657,7 @@
                 (ifaceUp) -> sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED, ifaceUp
                         ? ARG_LINKPROP_CHANGED_LINKSTATE_UP
                         : ARG_LINKPROP_CHANGED_LINKSTATE_DOWN),
-                config, mLog, mDependencies) {
+                config, mLog) {
             @Override
             public void onInterfaceAdded(String iface) {
                 super.onInterfaceAdded(iface);
@@ -816,8 +758,7 @@
         @Override
         public void startProvisioning(ProvisioningConfigurationParcelable req) {
             enforceNetworkStackCallingPermission();
-            IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req,
-                    mCallback.getInterfaceVersion()));
+            IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req));
         }
         @Override
         public void stop() {
@@ -906,7 +847,6 @@
 
     private void stopStateMachineUpdaters() {
         mObserverRegistry.unregisterObserver(mLinkObserver);
-        mLinkObserver.clearInterfaceParams();
         mLinkObserver.shutdown();
     }
 
@@ -920,28 +860,26 @@
                 false /* defaultEnabled */);
     }
 
-    @VisibleForTesting
-    static MacAddress getInitialBssid(final Layer2Information layer2Info,
-            final ScanResultInfo scanResultInfo, boolean isAtLeastS) {
-        MacAddress bssid = null;
+    private void setInitialBssid(final ProvisioningConfiguration req) {
+        final ScanResultInfo scanResultInfo = req.mScanResultInfo;
+        mCurrentBssid = 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) {
+        if (!ShimUtils.isAtLeastS() && scanResultInfo != null) {
             try {
-                bssid = MacAddress.fromString(scanResultInfo.getBssid());
+                mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());
             } catch (IllegalArgumentException e) {
-                Log.wtf(TAG, "Invalid BSSID: " + scanResultInfo.getBssid()
+                Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
                         + " in provisioning configuration", e);
             }
         }
-        if (bssid == null && layer2Info != null) {
-            bssid = layer2Info.mBssid;
+        if (mCurrentBssid == null && req.mLayer2Info != null) {
+            mCurrentBssid = req.mLayer2Info.mBssid;
         }
-        return bssid;
     }
 
     private boolean shouldDisableAcceptRaOnProvisioningLoss() {
@@ -972,8 +910,7 @@
             return;
         }
 
-        mCurrentBssid = getInitialBssid(req.mLayer2Info, req.mScanResultInfo,
-                ShimUtils.isAtLeastS());
+        setInitialBssid(req);
         if (req.mLayer2Info != null) {
             mL2Key = req.mLayer2Info.mL2Key;
             mCluster = req.mLayer2Info.mCluster;
@@ -1250,41 +1187,12 @@
         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
-    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)) {
+    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()) {
             return true;
         }
         if (config == null) {
@@ -1851,7 +1759,7 @@
 
     private boolean startIpReachabilityMonitor() {
         try {
-            mIpReachabilityMonitor = mDependencies.getIpReachabilityMonitor(
+            mIpReachabilityMonitor = new IpReachabilityMonitor(
                     mContext,
                     mInterfaceParams,
                     getHandler(),
@@ -1863,7 +1771,6 @@
                         }
                     },
                     mConfiguration.mUsingMultinetworkPolicyTracker,
-                    mDependencies.getIpReachabilityMonitorDeps(mContext, mInterfaceParams.name),
                     mNetd);
         } catch (IllegalArgumentException iae) {
             // Failed to start IpReachabilityMonitor. Log it and call
@@ -1945,7 +1852,7 @@
         }
 
         if (mIpReachabilityMonitor != null) {
-            mIpReachabilityMonitor.probeAll(true /* dueToRoam */);
+            mIpReachabilityMonitor.probeAll();
         }
 
         // Check whether to refresh previous IP lease on L2 roaming happened.
@@ -1970,6 +1877,7 @@
             mHasDisabledIpv6OrAcceptRaOnProvLoss = false;
             mGratuitousNaTargetAddresses.clear();
 
+            mLinkObserver.clearInterfaceParams();
             resetLinkProperties();
             if (mStartTimeMillis > 0) {
                 // Completed a life-cycle; send a final empty LinkProperties
@@ -2041,9 +1949,6 @@
             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.
@@ -2280,14 +2185,6 @@
         }
     }
 
-    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;
@@ -2298,19 +2195,10 @@
             apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
             apfConfig.multicastFilter = mMulticastFiltering;
             // Get the Configuration for ApfFilter from Context
-            // 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.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
+            apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
             apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
-            mApfFilter = mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
-                    mCallback);
+            mApfFilter = ApfFilter.maybeCreate(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) {
@@ -2320,13 +2208,13 @@
             mPacketTracker = createPacketTracker();
             if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);
 
-            if (isIpv6Enabled() && !startIPv6()) {
+            if (mConfiguration.mEnableIPv6 && !startIPv6()) {
                 doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
                 enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6);
                 return;
             }
 
-            if (isIpv4Enabled() && !isUsingPreconnection() && !startIPv4()) {
+            if (mConfiguration.mEnableIPv4 && !isUsingPreconnection() && !startIPv4()) {
                 doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
                 enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV4);
                 return;
@@ -2357,6 +2245,11 @@
                 mIpReachabilityMonitor = null;
             }
 
+            if (mDhcpClient != null) {
+                mDhcpClient.sendMessage(DhcpClient.CMD_STOP_DHCP);
+                mDhcpClient.doQuit();
+            }
+
             if (mPacketTracker != null) {
                 mPacketTracker.stop();
                 mPacketTracker = null;
@@ -2419,7 +2312,7 @@
                     // a DHCPv4 RENEW.  We used to do this on Wi-Fi framework
                     // roams.
                     if (mIpReachabilityMonitor != null) {
-                        mIpReachabilityMonitor.probeAll(false /* dueToRoam */);
+                        mIpReachabilityMonitor.probeAll();
                     }
                     break;
 
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index ff0aafe..cc4a851 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -16,7 +16,6 @@
 
 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;
@@ -28,17 +27,16 @@
 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;
@@ -109,7 +107,6 @@
         }
     }
 
-    private final Context mContext;
     private final String mInterfaceName;
     private final Callback mCallback;
     private final LinkProperties mLinkProperties;
@@ -118,15 +115,13 @@
     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, IpClient.Dependencies deps) {
-        mContext = context;
+            Configuration config, SharedLog log) {
         mInterfaceName = iface;
         mTag = "NetlinkTracker/" + mInterfaceName;
         mCallback = callback;
@@ -139,7 +134,6 @@
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mNetlinkMonitor = new MyNetlinkMonitor(h, log, mTag);
         mHandler.post(mNetlinkMonitor::start);
-        mDependencies = deps;
     }
 
     public void shutdown() {
@@ -159,11 +153,6 @@
         }
     }
 
-    private boolean isNetlinkEventParsingEnabled() {
-        return mDependencies.isFeatureEnabled(mContext, IPCLIENT_PARSE_NETLINK_EVENTS_VERSION,
-                false /* default value */);
-    }
-
     @Override
     public void onInterfaceRemoved(String iface) {
         maybeLog("interfaceRemoved", iface);
@@ -257,21 +246,17 @@
 
     @Override
     public void onInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
-        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();
+        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);
             }
-            mCallback.update(linkState);
         }
     }
 
@@ -423,15 +408,6 @@
             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;
@@ -441,12 +417,8 @@
                     processPref64Option((StructNdOptPref64) msg.option, whenMs);
                     break;
 
-                case StructNdOptRdnss.TYPE:
-                    processRdnssOption((StructNdOptRdnss) msg.option);
-                    break;
-
                 default:
-                    // TODO: implement DNSSL.
+                    // TODO: implement RDNSS and DNSSL.
                     break;
             }
         }
diff --git a/src/android/net/ip/IpReachabilityMonitor.java b/src/android/net/ip/IpReachabilityMonitor.java
index 0f199e2..3dbe662 100644
--- a/src/android/net/ip/IpReachabilityMonitor.java
+++ b/src/android/net/ip/IpReachabilityMonitor.java
@@ -20,8 +20,6 @@
 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;
@@ -32,6 +30,7 @@
 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;
@@ -41,21 +40,12 @@
 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;
@@ -153,10 +143,6 @@
     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 {
         /**
@@ -175,8 +161,6 @@
     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;
@@ -192,16 +176,6 @@
                         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();
-                }
             };
         }
     }
@@ -209,30 +183,25 @@
     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, Dependencies dependencies, final INetd netd) {
-        this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker, dependencies,
-                new IpConnectivityLog(), netd);
+            boolean usingMultinetworkPolicyTracker, final INetd netd) {
+        this(context, ifParams, h, log, callback, usingMultinetworkPolicyTracker,
+                Dependencies.makeDefault(context, ifParams.name), new IpConnectivityLog(), netd);
     }
 
     @VisibleForTesting
@@ -256,10 +225,7 @@
         // 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 {
-            int numResolicits = isMulticastResolicitEnabled()
-                    ? NUD_MCAST_RESOLICIT_NUM
-                    : INVALID_NUD_MCAST_RESOLICIT_NUM;
-            setNeighborParameters(MIN_NUD_SOLICIT_NUM, MIN_NUD_SOLICIT_INTERVAL_MS, numResolicits);
+            setNeighborParameters(MIN_NUD_SOLICIT_NUM, MIN_NUD_SOLICIT_INTERVAL_MS);
         } catch (Exception e) {
             Log.e(TAG, "Failed to adjust neighbor parameters with hardcoded defaults");
         }
@@ -275,16 +241,13 @@
                     // 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) {
-                        handleNeighborReachable(prev, event);
+                        maybeRestoreNeighborParameters();
                     }
                 });
         mIpNeighborMonitor.start();
-        mIpReachabilityMetrics = dependencies.getIpReachabilityMonitorMetrics();
     }
 
     public void stop() {
@@ -333,33 +296,6 @@
         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.
@@ -397,25 +333,6 @@
         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);
 
@@ -449,17 +366,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);
-            // TODO: remove |ip| when the callback signature no longer has
-            // an InetAddress argument.
-            mCallback.notifyLost(ip, logMsg);
+            if (mCallback != null) {
+                // TODO: remove |ip| when the callback signature no longer has
+                // an InetAddress argument.
+                mCallback.notifyLost(ip, logMsg);
+            }
         }
-        logNudFailed(event, type);
+        logNudFailed(lostProvisioning);
     }
 
     private void maybeRestoreNeighborParameters() {
@@ -483,13 +400,7 @@
         return !mUsingMultinetworkPolicyTracker || mCm.shouldAvoidBadWifi();
     }
 
-    /**
-     * 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) {
+    public void probeAll() {
         setNeighbourParametersPostRoaming();
 
         final List<InetAddress> ipProbeList = new ArrayList<>(mNeighborWatchList.keySet());
@@ -510,11 +421,6 @@
             logEvent(IpReachabilityEvent.PROBE, rval);
         }
         mLastProbeTimeMs = SystemClock.elapsedRealtime();
-        if (dueToRoam) {
-            mLastProbeDueToRoamMs = mLastProbeTimeMs;
-        } else {
-            mLastProbeDueToConfirmMs = mLastProbeTimeMs;
-        }
     }
 
     private long getProbeWakeLockDuration() {
@@ -544,12 +450,6 @@
 
     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,
@@ -564,117 +464,32 @@
                     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(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;
+    private void logNudFailed(boolean lostProvisioning) {
+        long duration = SystemClock.elapsedRealtime() - mLastProbeTimeMs;
+        boolean isFromProbe = (duration < getProbeWakeLockDuration());
+        int eventType = nudFailureEventType(isFromProbe, lostProvisioning);
         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 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;
+    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;
         }
     }
 }
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java
index 6dc2a5b..81d0c08 100755
--- a/src/android/net/util/NetworkStackUtils.java
+++ b/src/android/net/util/NetworkStackUtils.java
@@ -250,25 +250,11 @@
             "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");
     }
diff --git a/src/com/android/networkstack/metrics/IpProvisioningMetrics.java b/src/com/android/networkstack/metrics/IpProvisioningMetrics.java
index 5ca996e..b015a51 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
deleted file mode 100644
index 401de4a..0000000
--- a/src/com/android/networkstack/metrics/IpReachabilityMonitorMetrics.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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/stats.proto b/src/com/android/networkstack/metrics/stats.proto
index c09f082..2b0a704 100644
--- a/src/com/android/networkstack/metrics/stats.proto
+++ b/src/com/android/networkstack/metrics/stats.proto
@@ -172,19 +172,3 @@
     // 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 b5eafd6..770e85a 100644
--- a/src/com/android/networkstack/netlink/TcpSocketTracker.java
+++ b/src/com/android/networkstack/netlink/TcpSocketTracker.java
@@ -15,6 +15,13 @@
  */
 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;
@@ -31,18 +38,14 @@
 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;
@@ -63,10 +66,6 @@
 
 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;
@@ -115,7 +114,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;
@@ -161,7 +160,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
index ef38314..e6cdfc8 100644
--- a/src/com/android/networkstack/packets/NeighborAdvertisement.java
+++ b/src/com/android/networkstack/packets/NeighborAdvertisement.java
@@ -17,14 +17,13 @@
 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_HEADER_MIN_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;
@@ -51,12 +50,12 @@
     public final Icmpv6Header icmpv6Hdr;
     @NonNull
     public final NaHeader naHdr;
-    @Nullable
+    @NonNull
     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) {
+            @NonNull final NaHeader naHdr, @NonNull final LlaOption tlla) {
         this.ethHdr = ethHdr;
         this.ipv6Hdr = ipv6Hdr;
         this.icmpv6Hdr = icmpv6Hdr;
@@ -72,7 +71,7 @@
         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 int tllaOptionLen = Struct.getSize(LlaOption.class);
         final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv6HeaderLen
                 + icmpv6HeaderLen + naHeaderLen + tllaOptionLen);
 
@@ -80,9 +79,7 @@
         ipv6Hdr.writeToByteBuffer(packet);
         icmpv6Hdr.writeToByteBuffer(packet);
         naHdr.writeToByteBuffer(packet);
-        if (tlla != null) {
-            tlla.writeToByteBuffer(packet);
-        }
+        tlla.writeToByteBuffer(packet);
         packet.flip();
 
         return packet;
@@ -103,7 +100,7 @@
      */
     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
+        if (length < ETHER_HEADER_LEN + IPV6_HEADER_LEN + ICMPV6_HEADER_MIN_LEN
                 || recvbuf.length < length) {
             throw new ParseException("Invalid packet length: " + length);
         }
@@ -114,9 +111,7 @@
         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);
+        final LlaOption tlla = Struct.parse(LlaOption.class, packet);
 
         return new NeighborAdvertisement(ethHdr, ipv6Hdr, icmpv6Hdr, naHdr, tlla);
     }
diff --git a/src/com/android/networkstack/packets/NeighborSolicitation.java b/src/com/android/networkstack/packets/NeighborSolicitation.java
deleted file mode 100644
index 5c3e40a..0000000
--- a/src/com/android/networkstack/packets/NeighborSolicitation.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 948ce8d..7bc6a49 100755
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -16,7 +16,6 @@
 
 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;
@@ -32,10 +31,8 @@
 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.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;
@@ -389,15 +386,10 @@
     private static final int CMD_BANDWIDTH_CHECK_COMPLETE = 23;
 
     /**
-     * Message to self to know the bandwidth check has timed out.
+     * Message to self to know the bandwidth check is timeouted.
      */
     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;
@@ -422,6 +414,7 @@
     private String mPrivateDnsProviderHostname = "";
 
     private final Context mContext;
+    private final Context mCustomizedContext;
     private final INetworkMonitorCallbacks mCallback;
     private final int mCallbackVersion;
     private final Network mCleartextDnsNetwork;
@@ -436,21 +429,13 @@
     private final TcpSocketTracker mTcpTracker;
     // Configuration values for captive portal detection probes.
     private final String mCaptivePortalUserAgent;
-    // Configuration values in setting providers for captive portal detection probes
-    private final String mCaptivePortalHttpsUrlFromSetting;
-    private final String mCaptivePortalHttpUrlFromSetting;
+    private final URL[] mCaptivePortalFallbackUrls;
+    @NonNull
+    private final URL[] mCaptivePortalHttpUrls;
+    @NonNull
+    private final URL[] mCaptivePortalHttpsUrls;
     @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;
@@ -524,8 +509,7 @@
     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;
@@ -589,6 +573,7 @@
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         mNotifier = serviceManager.getNotifier();
+        mCustomizedContext = getCustomizedContextOrDefault();
 
         // CHECKSTYLE:OFF IndentationCheck
         addState(mDefaultState);
@@ -603,18 +588,16 @@
         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();
-        mCaptivePortalFallbackSpecs =
-                makeCaptivePortalFallbackProbeSpecs(getCustomizedContextOrDefault());
+        mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls();
+        mCaptivePortalHttpUrls = makeCaptivePortalHttpUrls();
+        mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
+        mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
         mRandom = deps.getRandom();
         // TODO: Evaluate to move data stall configuration to a specific class.
         mConsecutiveDnsTimeoutThreshold = getConsecutiveDnsTimeoutThreshold();
@@ -633,14 +616,7 @@
         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();
@@ -658,13 +634,6 @@
 
     /**
      * 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);
@@ -702,7 +671,6 @@
                 (Pair<LinkProperties, NetworkCapabilities>) connectedMsg.obj;
         mLinkProperties = attrs.first;
         mNetworkCapabilities = attrs.second;
-        suppressNotificationIfNetworkRestricted();
     }
 
     /**
@@ -767,12 +735,6 @@
         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) {
@@ -891,18 +853,6 @@
     // 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:
@@ -957,18 +907,6 @@
                             // 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);
@@ -1046,29 +984,12 @@
                     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:
@@ -1359,19 +1280,11 @@
                     //    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 (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 (!isValidationRequired()) {
                         if (isPrivateDnsValidationRequired()) {
                             validationLog("Network would not satisfy default request, "
                                     + "resolving private DNS");
@@ -1389,9 +1302,7 @@
                     return HANDLED;
                 case CMD_FORCE_REEVALUATION:
                     // The evaluation process restarts via EvaluatingState#enter.
-                    final boolean forceAccept = (message.arg2 != 0);
-                    return forceAccept || shouldAcceptForceRevalidation()
-                            ? NOT_HANDLED : HANDLED;
+                    return 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.
@@ -1643,13 +1554,8 @@
 
             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, httpsUrls, httpUrls, fallbackUrl))));
+                    isCaptivePortal(deps))));
             mThread.start();
         }
 
@@ -2039,24 +1945,18 @@
         }
 
         final long now = System.currentTimeMillis();
-        if (expTime < now || (expTime - now) > TEST_URL_EXPIRATION_MS) {
-            logw("Skipping test URL with expiration " + expTime + ", now " + now);
-            return null;
-        }
+        if (expTime < now || (expTime - now) > TEST_URL_EXPIRATION_MS) return null;
 
         final String strUrl = mDependencies.getDeviceConfigProperty(NAMESPACE_CONNECTIVITY,
                 key, null /* defaultValue */);
-        if (!isValidTestUrl(strUrl)) {
-            logw("Skipping invalid test URL " + strUrl);
-            return null;
-        }
+        if (!isValidTestUrl(strUrl)) return null;
         return makeURL(strUrl);
     }
 
-    private String getCaptivePortalServerHttpsUrl(@NonNull Context context) {
-        return getSettingFromResource(context,
-                R.string.config_captive_portal_https_url, mCaptivePortalHttpsUrlFromSetting,
-                context.getResources().getString(
+    private String getCaptivePortalServerHttpsUrl() {
+        return getSettingFromResource(mCustomizedContext,
+                R.string.config_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL,
+                mCustomizedContext.getResources().getString(
                 R.string.default_captive_portal_https_url));
     }
 
@@ -2133,10 +2033,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(@NonNull Context context) {
-        return getSettingFromResource(context,
-                R.string.config_captive_portal_http_url, mCaptivePortalHttpUrlFromSetting,
-                context.getResources().getString(
+    public String getCaptivePortalServerHttpUrl() {
+        return getSettingFromResource(mCustomizedContext,
+                R.string.config_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL,
+                mCustomizedContext.getResources().getString(
                 R.string.default_captive_portal_http_url));
     }
 
@@ -2172,13 +2072,13 @@
     }
 
     @VisibleForTesting
-    URL[] makeCaptivePortalFallbackUrls(@NonNull Context context) {
+    URL[] makeCaptivePortalFallbackUrls() {
         try {
             final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL,
                     null);
             final URL[] settingProviderUrls =
                 combineCaptivePortalUrls(firstUrl, CAPTIVE_PORTAL_OTHER_FALLBACK_URLS);
-            return getProbeUrlArrayConfig(context, settingProviderUrls,
+            return getProbeUrlArrayConfig(settingProviderUrls,
                     R.array.config_captive_portal_fallback_urls,
                     R.array.default_captive_portal_fallback_urls,
                     this::makeURL);
@@ -2189,7 +2089,7 @@
         }
     }
 
-    private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs(@NonNull Context context) {
+    private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs() {
         try {
             final String settingsValue = mDependencies.getDeviceConfigProperty(
                     NAMESPACE_CONNECTIVITY, CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
@@ -2199,7 +2099,7 @@
                     ? emptySpecs
                     : parseCaptivePortalProbeSpecs(settingsValue).toArray(emptySpecs);
 
-            return getProbeUrlArrayConfig(context, providerValue,
+            return getProbeUrlArrayConfig(providerValue,
                     R.array.config_captive_portal_fallback_probe_specs,
                     DEFAULT_CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS,
                     CaptivePortalProbeSpec::parseSpecOrNull);
@@ -2210,17 +2110,17 @@
         }
     }
 
-    private URL[] makeCaptivePortalHttpsUrls(@NonNull Context context) {
+    private URL[] makeCaptivePortalHttpsUrls() {
         final URL testUrl = getTestUrl(TEST_CAPTIVE_PORTAL_HTTPS_URL);
         if (testUrl != null) return new URL[] { testUrl };
 
-        final String firstUrl = getCaptivePortalServerHttpsUrl(context);
+        final String firstUrl = getCaptivePortalServerHttpsUrl();
         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(context, settingProviderUrls,
+            return getProbeUrlArrayConfig(settingProviderUrls,
                     R.array.config_captive_portal_https_urls,
                     DEFAULT_CAPTIVE_PORTAL_HTTPS_URLS, this::makeURL);
         } catch (Exception e) {
@@ -2231,17 +2131,17 @@
         }
     }
 
-    private URL[] makeCaptivePortalHttpUrls(@NonNull Context context) {
+    private URL[] makeCaptivePortalHttpUrls() {
         final URL testUrl = getTestUrl(TEST_CAPTIVE_PORTAL_HTTP_URL);
         if (testUrl != null) return new URL[] { testUrl };
 
-        final String firstUrl = getCaptivePortalServerHttpUrl(context);
+        final String firstUrl = getCaptivePortalServerHttpUrl();
         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(context, settingProviderUrls,
+            return getProbeUrlArrayConfig(settingProviderUrls,
                     R.array.config_captive_portal_http_urls,
                     DEFAULT_CAPTIVE_PORTAL_HTTP_URLS, this::makeURL);
         } catch (Exception e) {
@@ -2269,20 +2169,21 @@
      * <p>The configuration resource is prioritized, then the provider value.
      * @param context The context
      * @param configResource The resource id for the configuration parameter
-     * @param settingValue The value in the settings provider
+     * @param symbol The symbol 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 settingValue,
-            @NonNull String defaultValue) {
+            @StringRes int configResource, @NonNull String symbol, @NonNull String defaultValue) {
         final Resources res = context.getResources();
         String setting = res.getString(configResource);
 
         if (!TextUtils.isEmpty(setting)) return setting;
 
-        if (!TextUtils.isEmpty(settingValue)) return settingValue;
+        setting = mDependencies.getSetting(context, symbol, null);
+
+        if (!TextUtils.isEmpty(setting)) return setting;
 
         return defaultValue;
     }
@@ -2292,20 +2193,17 @@
      *
      * <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 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);
+    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);
     }
 
     /**
@@ -2313,18 +2211,15 @@
      *
      * <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 Context context, @NonNull T[] providerValue,
-            @ArrayRes int configResId, String[] defaultConfig,
-            @NonNull Function<String, T> resourceConverter) {
-        final Resources res = context.getResources();
+    private <T> T[] getProbeUrlArrayConfig(@NonNull T[] providerValue, @ArrayRes int configResId,
+            String[] defaultConfig, @NonNull Function<String, T> resourceConverter) {
+        final Resources res = mCustomizedContext.getResources();
         String[] configValue = res.getStringArray(configResId);
 
         if (configValue.length == 0) {
@@ -2403,14 +2298,15 @@
         }
     }
 
-    private CaptivePortalProbeResult isCaptivePortal(ValidationProperties properties,
-            URL[] httpsUrls, URL[] httpUrls, URL fallbackUrl) {
+    private CaptivePortalProbeResult isCaptivePortal(ValidationProperties properties) {
         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:
@@ -2451,7 +2347,7 @@
         } else if (mUseHttps && httpsUrls.length == 1 && httpUrls.length == 1) {
             // Probe results are reported inside sendHttpAndHttpsParallelWithFallbackProbes.
             result = sendHttpAndHttpsParallelWithFallbackProbes(properties, proxyInfo,
-                    httpsUrls[0], httpUrls[0], fallbackUrl);
+                    httpsUrls[0], httpUrls[0]);
         } else if (mUseHttps) {
             // Support result aggregation from multiple Urls.
             result = sendMultiParallelHttpAndHttpsProbes(properties, proxyInfo, httpsUrls,
@@ -2645,17 +2541,8 @@
 
         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);
         }
@@ -3053,8 +2940,7 @@
     }
 
     private CaptivePortalProbeResult sendHttpAndHttpsParallelWithFallbackProbes(
-            ValidationProperties properties, ProxyInfo proxy, URL httpsUrl, URL httpUrl,
-            URL fallbackUrl) {
+            ValidationProperties properties, ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
         // 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);
@@ -3100,10 +2986,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 fallback = (probeSpec != null) ? probeSpec.getUrl() : fallbackUrl;
+        final URL fallbackUrl = (probeSpec != null) ? probeSpec.getUrl() : nextFallbackUrl();
         CaptivePortalProbeResult fallbackProbeResult = null;
-        if (fallback != null) {
-            fallbackProbeResult = sendHttpProbe(fallback, PROBE_FALLBACK, probeSpec);
+        if (fallbackUrl != null) {
+            fallbackProbeResult = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
             reportHttpProbeResult(NETWORK_VALIDATION_PROBE_FALLBACK, fallbackProbeResult);
             if (fallbackProbeResult.isPortal()) {
                 return fallbackProbeResult;
@@ -3275,7 +3161,7 @@
          * data to statsd pipeline.
          * @param stats a {@link DataStallDetectionStats} that contains the detection level
          *              information.
-         * @param result the network reevaluation result.
+         * @para result the network reevaluation result.
          */
         public void writeDataStallDetectionStats(@NonNull final DataStallDetectionStats stats,
                 @NonNull final CaptivePortalProbeResult result) {
@@ -3485,28 +3371,18 @@
     // 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;
@@ -3540,26 +3416,9 @@
             });
         }
 
-        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;
@@ -3674,37 +3533,4 @@
                 && 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/integration/Android.bp b/tests/integration/Android.bp
index 9137c5c..43a0575 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -50,6 +50,7 @@
         "android.test.base",
         "android.test.mock",
     ],
+    jarjar_rules: ":NetworkStackJarJarRules",
     visibility: ["//visibility:private"],
 }
 
@@ -71,8 +72,6 @@
     platform_apis: true,
     test_suites: ["device-tests"],
     min_sdk_version: "29",
-    target_sdk_version: "30",
-    jarjar_rules: ":NetworkStackJarJarRules",
 }
 
 // Network stack next integration tests.
@@ -88,7 +87,22 @@
     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
@@ -98,7 +112,6 @@
     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"],
@@ -106,10 +119,8 @@
         "modules-utils-native-coverage-listener",
         "NetworkStackTestsLib",
         "NetworkStackIntegrationTestsLib",
-        "NetworkStaticLibTestsLib",
-        "NetdStaticLibTestsLib",
+        "NetworkStackStaticLibTestsLib",
     ],
     compile_multilib: "both",
     manifest: "AndroidManifest_coverage.xml",
-    jarjar_rules: ":NetworkStackJarJarRules",
 }
diff --git a/tests/integration/AndroidManifest.xml b/tests/integration/AndroidManifest.xml
index bfd3735..12f5d7d 100644
--- a/tests/integration/AndroidManifest.xml
+++ b/tests/integration/AndroidManifest.xml
@@ -16,6 +16,7 @@
 <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 fc91e59..660e42d 100644
--- a/tests/integration/AndroidManifest_coverage.xml
+++ b/tests/integration/AndroidManifest_coverage.xml
@@ -16,6 +16,7 @@
 <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/src/android/net/ip/IpClientIntegrationTest.kt b/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
index 748ee5a..eb0a799 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.kt
@@ -17,14 +17,8 @@
 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
@@ -62,23 +56,4 @@
     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 6ade54f..c121b3d 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTestCommon.java
@@ -27,10 +27,7 @@
 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;
@@ -43,21 +40,15 @@
 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_OFFSET;
-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_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;
 
@@ -108,7 +99,6 @@
 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;
@@ -118,10 +108,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;
@@ -129,7 +119,6 @@
 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;
@@ -146,13 +135,12 @@
 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.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;
@@ -160,10 +148,8 @@
 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;
@@ -180,7 +166,6 @@
 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;
@@ -224,7 +209,7 @@
  *
  * Tests in this class can either be run with signature permissions, or with root access.
  */
-@RunWith(Parameterized.class)
+@RunWith(AndroidJUnit4.class)
 @SmallTest
 public abstract class IpClientIntegrationTestCommon {
     private static final int DATA_BUFFER_LEN = 4096;
@@ -247,17 +232,6 @@
     @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.
      *
@@ -289,8 +263,6 @@
     @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;
@@ -300,7 +272,7 @@
 
     /***** END signature required test members *****/
 
-    protected IIpClientCallbacks mCb;
+    private IIpClientCallbacks mCb;
     private IIpClient mIIpClient;
     private String mIfaceName;
     private HandlerThread mPacketReaderThread;
@@ -355,10 +327,7 @@
     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 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 byte[] SERVER_MAC = new byte[] { 0x00, 0x1A, 0x11, 0x22, 0x33, 0x44 };
     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";
@@ -432,15 +401,6 @@
         }
 
         @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);
@@ -480,32 +440,6 @@
         }
 
         @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) {
@@ -536,14 +470,8 @@
 
     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
@@ -564,14 +492,8 @@
 
     @Before
     public void setUp() throws Exception {
-        // 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);
+        final Method testMethod = IpClientIntegrationTestCommon.class.getMethod(
+                mTestNameRule.getMethodName());
         mIsSignatureRequiredTest = testMethod.getAnnotation(SignatureRequiredTest.class) != null;
         assumeFalse(testSkipped());
 
@@ -584,12 +506,6 @@
         }
 
         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 {
@@ -602,7 +518,6 @@
         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);
@@ -797,14 +712,6 @@
         }
     }
 
-    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) {
@@ -854,7 +761,7 @@
 
     private void sendArpReply(final byte[] clientMac) throws IOException {
         final ByteBuffer packet = ArpPacket.buildArpPacket(clientMac /* dst */,
-                ROUTER_MAC_BYTES /* srcMac */, INADDR_ANY.getAddress() /* target IP */,
+                SERVER_MAC /* src */, INADDR_ANY.getAddress() /* target IP */,
                 clientMac /* target HW address */, CLIENT_ADDR.getAddress() /* sender IP */,
                 (short) ARP_REPLY);
         mPacketReader.sendResponse(packet);
@@ -862,7 +769,7 @@
 
     private void sendArpProbe() throws IOException {
         final ByteBuffer packet = ArpPacket.buildArpPacket(DhcpPacket.ETHER_BROADCAST /* dst */,
-                ROUTER_MAC_BYTES /* srcMac */, CLIENT_ADDR.getAddress() /* target IP */,
+                SERVER_MAC /* src */, CLIENT_ADDR.getAddress() /* target IP */,
                 new byte[ETHER_ADDR_LEN] /* target HW address */,
                 INADDR_ANY.getAddress() /* sender IP */, (short) ARP_REQUEST);
         mPacketReader.sendResponse(packet);
@@ -1551,23 +1458,20 @@
         HandlerUtils.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
     }
 
-    private boolean isIcmpv6PacketOfType(final byte[] packetBytes, int type) {
+    private boolean isRouterSolicitation(final byte[] packetBytes) {
         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) type;
-    }
-
-    private boolean isRouterSolicitation(final byte[] packetBytes) {
-        return isIcmpv6PacketOfType(packetBytes, ICMPV6_ROUTER_SOLICITATION);
+                && packet.get(ETHER_HEADER_LEN + IPV6_HEADER_LEN)
+                        == (byte) 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);
+        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_NEIGHBOR_ADVERTISEMENT;
     }
 
     private NeighborAdvertisement getNextNeighborAdvertisement() throws ParseException {
@@ -1580,16 +1484,6 @@
         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 {
         assertNotNull("No router solicitation received on interface within timeout",
                 mPacketReader.popPacket(PACKET_TIMEOUT_MS, this::isRouterSolicitation));
@@ -1627,18 +1521,17 @@
         return RdnssOption.build(lifetime, servers);
     }
 
-    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 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);
+        final MacAddress dstMac = MacAddress.fromString("33:33:00:00:00:01");
+        final MacAddress srcMac = MacAddress.fromString("01:02:03:04:05:06");
+        final Inet6Address routerLinkLocal =
+                (Inet6Address) InetAddresses.parseNumericAddress("fe80::1");
+
+        return Ipv6Utils.buildRaPacket(srcMac, dstMac, routerLinkLocal,
+                IPV6_ADDR_ALL_NODES_MULTICAST, (byte) 0 /* M=0, O=0 */, lifetime,
+                0 /* Reachable time, unspecified */, 100 /* Retrans time 100ms */,
+                options);
     }
 
     private static ByteBuffer buildRaPacket(ByteBuffer... options) throws Exception {
@@ -1682,8 +1575,7 @@
         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);
+        final ByteBuffer ra = buildRaPacket(pio, rdnss);
 
         return doIpv6OnlyProvisioning(inOrder, ra);
     }
@@ -2108,52 +2000,6 @@
     }
 
     @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 */,
@@ -2537,8 +2383,7 @@
         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);
+        final ByteBuffer ra = buildRaPacket(pio, rdnss);
 
         doIpv6OnlyProvisioning(inOrder, ra);
 
@@ -2762,20 +2607,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 {
-        setUpRetrievedNetworkAttributesForInitRebootState();
+        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());
 
         final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                 .withoutIpReachabilityMonitor()
@@ -2902,7 +2747,7 @@
     );
 
     private DhcpPacket doCustomizedDhcpOptionsTest(final List<DhcpOption> options,
-             final ScanResultInfo info, boolean isDhcpLeaseCacheEnabled) throws Exception {
+             final ScanResultInfo info) throws Exception {
         ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
                 .withoutIpReachabilityMonitor()
                 .withLayer2Information(new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
@@ -2911,7 +2756,7 @@
                 .withDhcpOptions(options)
                 .withoutIPv6();
 
-        setDhcpFeatures(isDhcpLeaseCacheEnabled, false /* isRapidCommitEnabled */,
+        setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, false /* isRapidCommitEnabled */,
                 false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
 
         startIpClientProvisioning(prov.build());
@@ -2922,11 +2767,10 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions() throws Exception {
+    public void testCustomizedDhcpOptions() 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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
@@ -2934,11 +2778,10 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_nullDhcpOptions() throws Exception {
+    public void testCustomizedDhcpOptions_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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(null /* options */, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2946,9 +2789,9 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_nullScanResultInfo() throws Exception {
+    public void testCustomizedDhcpOptions_nullScanResultInfo() throws Exception {
         final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS,
-                null /* scanResultInfo */, false /* isDhcpLeaseCacheEnabled */);
+                null /* scanResultInfo */);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2956,11 +2799,10 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_disallowedOui() throws Exception {
+    public void testCustomizedDhcpOptions_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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2968,11 +2810,10 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_invalidIeId() throws Exception {
+    public void testCustomizedDhcpOptions_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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2980,11 +2821,10 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_invalidVendorSpecificType() throws Exception {
+    public void testCustomizedDhcpOptions_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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(TEST_OEM_DHCP_OPTIONS, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, new String("android-dhcp-" + Build.VERSION.RELEASE));
@@ -2992,7 +2832,7 @@
     }
 
     @Test
-    public void testDisoverCustomizedDhcpOptions_disallowedOption() throws Exception {
+    public void testCustomizedDhcpOptions_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),
@@ -3000,8 +2840,7 @@
                 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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
@@ -3010,7 +2849,7 @@
     }
 
     @Test
-    public void testDiscoverCustomizedDhcpOptions_disallowedParamRequestOption() throws Exception {
+    public void testCustomizedDhcpOptions_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),
@@ -3018,8 +2857,7 @@
                 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,
-                false /* isDhcpLeaseCacheEnabled */);
+        final DhcpPacket packet = doCustomizedDhcpOptionsTest(options, info);
 
         assertTrue(packet instanceof DhcpDiscoverPacket);
         assertEquals(packet.mVendorId, TEST_OEM_VENDOR_ID);
@@ -3027,160 +2865,6 @@
         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);
@@ -3281,7 +2965,7 @@
     @Test
     public void testGratuitousArpAndNaAfterRoaming_disableExpFlag() throws Exception {
         startGratuitousArpAndNaAfterRoamingTest(false /* isGratuitousArpNaRoamingEnabled */,
-                true /* hasIpv4 */, true /* hasIpv6 */);
+                true /* hasIpv6 */, true /* hasIpv6 */);
         performDualStackProvisioning();
         forceLayer2Roaming();
 
@@ -3324,206 +3008,118 @@
         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 doInitialBssidSetupTest(final Layer2Information layer2Info,
+            final ScanResultInfo scanResultInfo) throws Exception {
+        ProvisioningConfiguration.Builder prov = new ProvisioningConfiguration.Builder()
+                .withoutIpReachabilityMonitor()
+                .withLayer2Information(layer2Info)
+                .withScanResultInfo(scanResultInfo)
+                .withDisplayName("\"0001docomo\"")
+                .withoutIPv6();
 
-    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);
-    }
+        setDhcpFeatures(false /* isDhcpLeaseCacheEnabled */, true /* shouldReplyRapidCommitAck */,
+                false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
+        startIpClientProvisioning(prov.build());
 
-    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.
+        handleDhcpPackets(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
+                true /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, null /* serverSentUrl */);
+        verifyIPv4OnlyProvisioningSuccess(Collections.singletonList(CLIENT_ADDR));
         forceLayer2Roaming();
     }
 
-    @Test
-    public void testIpReachabilityMonitor_probeFailed() throws Exception {
-        prepareIpReachabilityMonitorTest();
+    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromLayer2Info() throws Exception {
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_DEFAULT_BSSID));
 
-        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 */);
+        doInitialBssidSetupTest(layer2Info, null /* scanResultInfo */);
+
+        // Initial BSSID comes from layer2Info, it's different with target roaming bssid,
+        // then verify that DHCPREQUEST packet is sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket();
+        assertTrue(packet instanceof DhcpRequestPacket);
     }
 
-    @Test
-    public void testIpReachabilityMonitor_probeReachable() throws Exception {
-        prepareIpReachabilityMonitorTest();
+    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromLayer2Info_NullBssid() throws Exception {
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                null /* bssid */);
+        final ScanResultInfo scanResultInfo =
+                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DHCP_ROAM_BSSID);
 
-        final NeighborSolicitation ns = waitForUnicastNeighborSolicitation(ROUTER_MAC /* dstMac */,
-                ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+        doInitialBssidSetupTest(layer2Info, scanResultInfo);
 
-        // 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();
+        // Initial BSSID comes from layer2Info, it's null, no DHCPREQUEST packet
+        // will be sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
+        assertNull(packet);
     }
 
-    @Test
-    public void testIpReachabilityMonitor_mcastResoclicitProbeFailed() throws Exception {
-        prepareIpReachabilityMonitorTest(true /* isMulticastResolicitEnabled */);
+    @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromLayer2Info_SameRoamingBssid() throws Exception {
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_DHCP_ROAM_BSSID));
 
-        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 */);
+        doInitialBssidSetupTest(layer2Info, null /* scanResultInfo */);
+
+        // Initial BSSID comes from layer2Info, it's same with target roaming bssid,
+        // no DHCPREQUEST packet will be sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
+        assertNull(packet);
     }
 
-    @Test
-    public void testIpReachabilityMonitor_mcastResoclicitProbeReachableWithSameLinkLayerAddress()
+    @Test @IgnoreAfter(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromScanResultInfo() throws Exception {
+        final ScanResultInfo scanResultInfo =
+                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DEFAULT_BSSID);
+
+        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
+
+        // Initial BSSID comes from ScanResultInfo, it's different with target roaming bssid,
+        // then verify that DHCPREQUEST packet is sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket();
+        assertTrue(packet instanceof DhcpRequestPacket);
+    }
+
+    @Test @IgnoreAfter(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromScanResultInfo_SameRoamingBssid() throws Exception {
+        final ScanResultInfo scanResultInfo =
+                makeScanResultInfo(TEST_DEFAULT_SSID, TEST_DHCP_ROAM_BSSID);
+
+        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
+
+        // Initial BSSID comes from ScanResultInfo, it's same with target roaming bssid,
+        // no DHCPREQUEST packet will be sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
+        assertNull(packet);
+    }
+
+    @Test @IgnoreAfter(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromScanResultInfo_BrokenInitialBssid() throws Exception {
+        final ScanResultInfo scanResultInfo =
+                makeScanResultInfo(TEST_DEFAULT_SSID, "00:11:22:33:44:");
+
+        doInitialBssidSetupTest(null /* layer2Info */, scanResultInfo);
+
+        // Initial BSSID comes from ScanResultInfo, it's broken MAC address format and fallback
+        // to null layer2Info, no DHCPREQUEST packet will be sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket(TEST_TIMEOUT_MS);
+        assertNull(packet);
+    }
+
+    @Test @IgnoreAfter(Build.VERSION_CODES.R)
+    public void testSetInitialBssidFromScanResultInfo_BrokenInitialBssidFallback()
             throws Exception {
-        prepareIpReachabilityMonitorTest(true /* isMulticastResolicitEnabled */);
+        final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER,
+                MacAddress.fromString(TEST_DEFAULT_BSSID));
+        final ScanResultInfo scanResultInfo =
+                makeScanResultInfo(TEST_DEFAULT_SSID, "00:11:22:33:44:");
 
-        final NeighborSolicitation ns = waitForUnicastNeighborSolicitation(ROUTER_MAC /* dstMac */,
-                ROUTER_LINK_LOCAL /* dstIp */, ROUTER_LINK_LOCAL /* targetIp */);
+        doInitialBssidSetupTest(layer2Info, scanResultInfo);
 
-        // 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()
-        );
+        // Initial BSSID comes from ScanResultInfo, it's broken MAC address format and fallback
+        // to check layer2Info, then verify DHCPREQUEST packet will be sent after roaming.
+        final DhcpPacket packet = getNextDhcpPacket();
+        assertTrue(packet instanceof DhcpRequestPacket);
     }
 }
diff --git a/tests/integration/src/android/net/ip/IpClientRootTest.kt b/tests/integration/src/android/net/ip/IpClientRootTest.kt
index d861639..68d8aab 100644
--- a/tests/integration/src/android/net/ip/IpClientRootTest.kt
+++ b/tests/integration/src/android/net/ip/IpClientRootTest.kt
@@ -33,7 +33,6 @@
 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
@@ -46,8 +45,6 @@
 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
 
@@ -153,7 +150,6 @@
             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
@@ -264,16 +260,4 @@
         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 0329fab..e474d8a 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 com.android.net.module.util.netlink;
+package android.net.netlink;
 
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index fa054fe..e308b96 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -36,10 +36,7 @@
         "android.test.base",
         "android.test.mock",
     ],
-    defaults: [
-        "framework-connectivity-test-defaults",
-        "libnetworkstackutilsjni_deps"
-    ],
+    defaults: ["libnetworkstackutilsjni_deps"],
     jni_libs: [
         // For mockito extended
         "libdexmakerjvmtiagent",
@@ -47,6 +44,7 @@
         "libnetworkstackutilsjni",
     ],
     jni_uses_sdk_apis: true,
+    jarjar_rules: ":NetworkStackJarJarRules",
 }
 
 // Tests for NetworkStackNext.
@@ -60,7 +58,7 @@
     defaults: ["NetworkStackTestsDefaults"],
     static_libs: ["NetworkStackApiCurrentLib"],
     compile_multilib: "both", // Workaround for b/147785146 for mainline-presubmit
-    jarjar_rules: ":NetworkStackJarJarRules",
+    enabled: false, // Disabled in mainline-prod
 }
 
 // Library containing the unit tests. This is used by the coverage test target to pull in the
@@ -73,8 +71,8 @@
     static_libs: ["NetworkStackApiStableLib"],
     visibility: [
         "//packages/modules/NetworkStack/tests/integration",
-        "//packages/modules/Connectivity/tests:__subpackages__",
-        "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
+        "//frameworks/base/packages/Tethering/tests/integration",
+        "//packages/modules/Connectivity/Tethering/tests/integration",
     ]
 }
 
@@ -87,7 +85,6 @@
     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/lint-baseline.xml b/tests/unit/lint-baseline.xml
index 0bfcaa9..ededbea 100644
--- a/tests/unit/lint-baseline.xml
+++ b/tests/unit/lint-baseline.xml
@@ -3,6 +3,105 @@
 
     <issue
         id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="    private static final NetworkCapabilities CELL_METERED_CAPABILITIES = new NetworkCapabilities()"
+        errorLine2="                                                                         ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="297"
+            column="74"/>
+    </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/server/connectivity/NetworkMonitorTest.java"
+            line="302"
+            column="13"/>
+    </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/server/connectivity/NetworkMonitorTest.java"
+            line="308"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="            new NetworkCapabilities().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="314"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="        final NetworkCapabilities nc = new NetworkCapabilities()"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="670"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="        final NetworkCapabilities nc = new NetworkCapabilities()"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="690"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="        final NetworkCapabilities meteredCap = new NetworkCapabilities()"
+        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="726"
+            column="48"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="        final NetworkCapabilities nonMeteredCap = new NetworkCapabilities()"
+        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="746"
+            column="51"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
+        errorLine1="        final NetworkCapabilities nc = new NetworkCapabilities()"
+        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
+            line="2149"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
         message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
         errorLine1="    private val EMPTY_CAPABILITIES = NetworkCapabilities()"
         errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~">
@@ -78,4 +177,81 @@
             column="14"/>
     </issue>
 
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        mCallback.onCapabilitiesChanged(net2097, NetworkCapabilities())"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="59"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        mCallback.onCapabilitiesChanged(net2098, NetworkCapabilities())"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="71"
+            column="50"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        val meteredNc = NetworkCapabilities()"
+        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="108"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        val unmeteredNc = NetworkCapabilities().addCapability(NOT_METERED)"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="109"
+            column="27"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        val netCaps = NetworkCapabilities().addTransportType(CELLULAR)"
+        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="130"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="        val netCaps = NetworkCapabilities().addCapability(NOT_METERED).addTransportType(WIFI)"
+        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="152"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
+        errorLine1="            &quot;CapabilitiesChanged&quot; -> cb.onCapabilitiesChanged(net, NetworkCapabilities())"
+        errorLine2="                                                                   ~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="packages/modules/NetworkStack/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt"
+            line="279"
+            column="68"/>
+    </issue>
+
 </issues>
diff --git a/tests/unit/src/android/net/dhcp/DhcpPacketTest.java b/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
index 1a1f6c3..d0c49d3 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.sTestOverrideVendorId = "android-dhcp-???";
+        DhcpPacket.testOverrideVendorId = "android-dhcp-???";
     }
 
     @After
     public void tearDown() {
-        DhcpPacket.sTestOverrideVendorId = null;
+        DhcpPacket.testOverrideVendorId = 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 fc0d52b..6e9078e 100644
--- a/tests/unit/src/android/net/ip/ConntrackMonitorTest.java
+++ b/tests/unit/src/android/net/ip/ConntrackMonitorTest.java
@@ -16,16 +16,15 @@
 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;
@@ -34,6 +33,8 @@
 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;
@@ -45,9 +46,6 @@
 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 95fe93a..e991ea7 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -18,15 +18,12 @@
 
 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;
@@ -51,32 +48,22 @@
 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;
@@ -86,12 +73,9 @@
 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;
 
 
@@ -101,9 +85,6 @@
 @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";
@@ -113,9 +94,6 @@
     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 = {
@@ -431,7 +409,6 @@
 
     @Test
     public void testIsProvisioned() throws Exception {
-        final IpClient ipc = makeIpClient(TEST_IFNAME);
         InitialConfiguration empty = conf(links(), prefixes());
         IsProvisionedTestCase[] testcases = {
             // nothing
@@ -463,7 +440,7 @@
         };
 
         for (IsProvisionedTestCase testcase : testcases) {
-            if (ipc.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
+            if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
                 fail(testcase.errorMessage());
             }
         }
@@ -654,183 +631,6 @@
         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 ea8f1da..863e268 100644
--- a/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
+++ b/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.kt
@@ -16,7 +16,6 @@
 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
@@ -24,37 +23,19 @@
 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
@@ -62,15 +43,12 @@
 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
@@ -88,20 +66,12 @@
 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 {
@@ -121,54 +91,6 @@
     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.
  */
@@ -182,7 +104,6 @@
     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) }
@@ -250,8 +171,6 @@
             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
@@ -288,8 +207,8 @@
         verify(callback, timeout(TEST_TIMEOUT_MS)).notifyLost(eq(TEST_IPV4_DNS), anyString())
     }
 
-    private fun runLoseProvisioningTest(newLp: LinkProperties, lostNeighbor: InetAddress) {
-        reachabilityMonitor.updateLinkProperties(newLp)
+    private fun runLoseProvisioningTest(lostNeighbor: InetAddress) {
+        reachabilityMonitor.updateLinkProperties(TEST_LINK_PROPERTIES)
 
         neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV4_GATEWAY, NUD_STALE))
         neighborMonitor.enqueuePacket(makeNewNeighMessage(TEST_IPV6_GATEWAY, NUD_STALE))
@@ -300,261 +219,23 @@
         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_LINK_PROPERTIES, TEST_IPV4_DNS)
+        runLoseProvisioningTest(TEST_IPV4_DNS)
     }
 
     @Test
     fun testLoseProvisioning_Ipv6DnsLost() {
-        runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_DNS)
+        runLoseProvisioningTest(TEST_IPV6_DNS)
     }
 
     @Test
     fun testLoseProvisioning_Ipv4GatewayLost() {
-        runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV4_GATEWAY)
+        runLoseProvisioningTest(TEST_IPV4_GATEWAY)
     }
 
     @Test
     fun testLoseProvisioning_Ipv6GatewayLost() {
-        runLoseProvisioningTest(TEST_LINK_PROPERTIES, TEST_IPV6_GATEWAY)
+        runLoseProvisioningTest(TEST_IPV6_GATEWAY)
     }
-
-    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)
-    }
-}
+}
\ No newline at end of file
diff --git a/tests/unit/src/android/net/netlink/ConntrackMessageTest.java b/tests/unit/src/android/net/netlink/ConntrackMessageTest.java
new file mode 100644
index 0000000..2e8d184
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/ConntrackMessageTest.java
@@ -0,0 +1,433 @@
+/*
+ * 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
new file mode 100644
index 0000000..fcc85a2
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/InetDiagSocketTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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
new file mode 100644
index 0000000..b070d61
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NduseroptMessageTest.java
@@ -0,0 +1,246 @@
+/*
+ * 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
new file mode 100644
index 0000000..131feeb
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NetlinkConstantsTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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
new file mode 100644
index 0000000..345622f
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NetlinkErrorMessageTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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
new file mode 100644
index 0000000..5716803
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NetlinkSocketTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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
new file mode 100644
index 0000000..3b485eb
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/NetlinkTestUtils.kt
@@ -0,0 +1,102 @@
+/*
+ * 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
new file mode 100644
index 0000000..a1f1d44
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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
new file mode 100644
index 0000000..0f3020d
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java
@@ -0,0 +1,201 @@
+/*
+ * 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
new file mode 100644
index 0000000..b44b31d
--- /dev/null
+++ b/tests/unit/src/android/net/netlink/StructNlMsgHdrTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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 716abaa..436b81a 100644
--- a/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
+++ b/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
@@ -17,22 +17,12 @@
 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;
@@ -86,66 +76,32 @@
         return options;
     }
 
-    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));
-        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
-        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"));
-        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();
+        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(
+                new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
+        mConfig.mStaticIpConfig = new StaticIpConfiguration();
+        mConfig.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",
+                MacAddress.fromString("00:01:02:03:04:05"));
+        mConfig.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
+                new String("android-dhcp-11").getBytes());
         // Any added field must be included in equals() to be tested properly
         assertFieldCountEquals(16, ProvisioningConfiguration.class);
     }
@@ -197,43 +153,9 @@
         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(), 12 /* interface version */);
+                fromStableParcelable(mConfig.toStableParcelable());
         assertEquals(mConfig, unparceled);
     }
 
@@ -241,6 +163,8 @@
     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++);
@@ -274,10 +198,6 @@
                   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);
     }
 
@@ -303,8 +223,7 @@
             + " 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]}],"
-            + " ipv4ProvisioningMode: 2, ipv6ProvisioningMode: 1}";
+            + " value: [97, 110, 100, 114, 111, 105, 100, 45, 100, 104, 99, 112, 45, 49, 49]}]}";
 
     @Test
     public void testParcelableToString() {
@@ -316,17 +235,4 @@
         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 5ca20d8..5b91985 100644
--- a/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
+++ b/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
@@ -1,6 +1,5 @@
 package android.net.testutils
 
-import android.annotation.SuppressLint
 import android.net.LinkAddress
 import android.net.LinkProperties
 import android.net.Network
@@ -8,15 +7,6 @@
 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
@@ -43,7 +33,6 @@
 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
 
@@ -113,20 +102,6 @@
     }
 
     @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)
@@ -270,41 +245,6 @@
             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)
@@ -314,7 +254,6 @@
     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
@@ -350,26 +289,5 @@
     },
     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/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java b/tests/unit/src/com/android/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java
deleted file mode 100644
index 45592aa..0000000
--- a/tests/unit/src/com/android/networkstack/metrics/NetworkIpReachabilityMonitorMetricsTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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 198ac99..8fbe0c4 100644
--- a/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
+++ b/tests/unit/src/com/android/networkstack/netlink/TcpSocketTrackerTest.java
@@ -16,6 +16,7 @@
 
 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;
@@ -25,7 +26,6 @@
 
 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,6 +43,7 @@
 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;
@@ -50,7 +51,6 @@
 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
index c689d7b..3317b2b 100644
--- a/tests/unit/src/com/android/networkstack/packets/NeighborAdvertisementTest.java
+++ b/tests/unit/src/com/android/networkstack/packets/NeighborAdvertisementTest.java
@@ -19,7 +19,6 @@
 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;
@@ -91,41 +90,6 @@
         // 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,
@@ -151,10 +115,6 @@
         (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
@@ -192,7 +152,7 @@
         (byte) 0xb9, (byte) 0x0c, (byte) 0x31, (byte) 0x78,
         // TLLA option
         (byte) 0x02, (byte) 0x01,
-        // truncatd Link-Layer address: 4bytes
+        // Link-Layer address
         (byte) 0xea, (byte) 0xbe, (byte) 0x11, (byte) 0x25,
     };
 
@@ -205,8 +165,11 @@
         assertArrayEquals(na.array(), TEST_GRATUITOUS_NA);
     }
 
-    private void assertNeighborAdvertisement(final NeighborAdvertisement na,
-            boolean hasTllaOption) {
+    @Test
+    public void testGratuitousNa_parse() throws Exception {
+        final NeighborAdvertisement na = NeighborAdvertisement.parse(TEST_GRATUITOUS_NA,
+                TEST_GRATUITOUS_NA.length);
+
         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);
@@ -218,46 +181,20 @@
         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());
-        }
-    }
+        assertEquals(2, 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 {
+    public void testGratuitousNa_invalidByteBufferParameters() 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,
diff --git a/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java b/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java
deleted file mode 100644
index 18a3ef3..0000000
--- a/tests/unit/src/com/android/networkstack/packets/NeighborSolicitationTest.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package 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 cf65cd7..b32a419 100644
--- a/tests/unit/src/com/android/server/NetworkStackServiceTest.kt
+++ b/tests/unit/src/com/android/server/NetworkStackServiceTest.kt
@@ -43,6 +43,7 @@
 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
@@ -206,10 +207,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) {
+        assertThrows(SecurityException::class.java, ExceptionUtils.ThrowingRunnable {
             // 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 ff43325..f010007 100644
--- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -16,9 +16,7 @@
 
 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;
@@ -27,14 +25,9 @@
 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;
@@ -98,7 +91,6 @@
 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;
@@ -163,7 +155,6 @@
 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;
 
@@ -210,7 +201,6 @@
 
 @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";
@@ -325,14 +315,6 @@
     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.
      *
@@ -590,7 +572,7 @@
     }
 
     private void resetCallbacks() {
-        resetCallbacks(11);
+        resetCallbacks(6);
     }
 
     private void resetCallbacks(int interfaceVersion) {
@@ -638,7 +620,6 @@
 
         @Override
         protected void onQuitting() {
-            super.onQuitting();
             assertTrue(mCreatedNetworkMonitors.remove(this));
             mQuitCv.open();
         }
@@ -865,6 +846,7 @@
 
     @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);
@@ -872,21 +854,16 @@
                 R.string.default_captive_portal_http_url);
         when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
                 .thenReturn(TEST_HTTP_OTHER_URL1);
-        final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
-        assertEquals(TEST_HTTP_URL, wnm.getCaptivePortalServerHttpUrl(mContext));
+        assertEquals(TEST_HTTP_URL, wnm.getCaptivePortalServerHttpUrl());
         // 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(mContext));
+        assertEquals(TEST_HTTP_OTHER_URL1, wnm.getCaptivePortalServerHttpUrl());
         // If both config_captive_portal_http_url and global setting are unset,
-        // default_captive_portal_http_url is used. But the global setting will only be read in the
-        // constructor.
+        // default_captive_portal_http_url is used.
         when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTP_URL), any()))
                 .thenReturn(null);
-        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));
+        assertEquals(TEST_HTTP_OTHER_URL2, wnm.getCaptivePortalServerHttpUrl());
     }
 
     @Test
@@ -943,57 +920,6 @@
         }
     }
 
-    @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", "", "");
@@ -1024,7 +950,7 @@
     public void testMakeFallbackUrls() throws Exception {
         final WrappedNetworkMonitor wnm = makeCellNotMeteredNetworkMonitor();
         // Value exist in setting provider.
-        URL[] urls = wnm.makeCaptivePortalFallbackUrls(mContext);
+        URL[] urls = wnm.makeCaptivePortalFallbackUrls();
         assertEquals(urls[0].toString(), TEST_FALLBACK_URL);
 
         // Clear setting provider value. Verify it to get configuration from resource instead.
@@ -1032,13 +958,13 @@
         // Verify that getting resource with exception.
         when(mResources.getStringArray(R.array.config_captive_portal_fallback_urls))
                 .thenThrow(Resources.NotFoundException.class);
-        urls = wnm.makeCaptivePortalFallbackUrls(mContext);
+        urls = wnm.makeCaptivePortalFallbackUrls();
         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(mContext);
+        urls = wnm.makeCaptivePortalFallbackUrls();
         assertEquals(urls.length, 2);
         assertEquals("http://testUrl1.com", urls[0].toString());
         assertEquals("http://testUrl2.com", urls[1].toString());
@@ -1049,7 +975,7 @@
         setupNoSimCardNeighborMcc();
         doReturn(new String[] {"http://testUrl3.com"}).when(mMccResource)
                 .getStringArray(R.array.config_captive_portal_fallback_urls);
-        urls = wnm.makeCaptivePortalFallbackUrls(mContext);
+        urls = wnm.makeCaptivePortalFallbackUrls();
         assertEquals(urls.length, 2);
         assertEquals("http://testUrl1.com", urls[0].toString());
         assertEquals("http://testUrl2.com", urls[1].toString());
@@ -1062,7 +988,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(mMccContext);
+        final URL[] urls = wnm.makeCaptivePortalFallbackUrls();
         assertEquals(urls.length, 1);
         assertEquals("http://testUrl.com", urls[0].toString());
     }
@@ -1142,34 +1068,6 @@
         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);
@@ -1853,105 +1751,25 @@
         runFailedNetworkTest();
     }
 
-    private void doValidationSkippedTest(NetworkCapabilities nc, int validationResult)
-            throws Exception {
-        runNetworkTest(TEST_LINK_PROPERTIES, nc, validationResult,
-                0 /* probesSucceeded */, null /* redirectUrl */);
+    @Test
+    public void testNoInternetCapabilityValidated() throws Exception {
+        runNetworkTest(TEST_LINK_PROPERTIES, CELL_NO_INTERNET_CAPABILITIES,
+                NETWORK_VALIDATION_RESULT_VALID, 0 /* probesSucceeded */, null /* redirectUrl */);
         verify(mCleartextDnsNetwork, never()).openConnection(any());
     }
 
     @Test
-    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 {
+    public void testLaunchCaptivePortalApp() 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());
 
-        assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
+        assertEquals(1, mRegisteredReceivers.size());
 
         // Check that startCaptivePortalApp sends the expected intent.
         nm.launchCaptivePortalApp();
@@ -1972,49 +1790,17 @@
         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));
-        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));
+        assertEquals(0, mRegisteredReceivers.size());
     }
 
     @Test
@@ -2575,7 +2361,7 @@
         verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
             .showProvisioningNotification(any(), any());
 
-        assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
+        assertEquals(1, mRegisteredReceivers.size());
         // Check that startCaptivePortalApp sends the expected intent.
         nm.launchCaptivePortalApp();
 
@@ -2797,7 +2583,7 @@
         monitor.notifyNetworkConnected(linkProperties, networkCapabilities);
         verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                 .showProvisioningNotification(any(), any());
-        assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
+        assertEquals(1, mRegisteredReceivers.size());
         verifyNetworkTested(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, TEST_LOGIN_URL);
 
         // Force reevaluation and confirm that the network is still captive
@@ -2818,64 +2604,6 @@
                         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))
@@ -2960,21 +2688,21 @@
     private NetworkMonitor runPortalNetworkTest() throws RemoteException {
         final NetworkMonitor nm = runNetworkTest(VALIDATION_RESULT_PORTAL,
                 0 /* probesSucceeded */, TEST_LOGIN_URL);
-        assertCaptivePortalAppReceiverRegistered(true /* isPortal */);
+        assertEquals(1, mRegisteredReceivers.size());
         return nm;
     }
 
     private NetworkMonitor runNoValidationNetworkTest() throws RemoteException {
         final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_VALID,
                 0 /* probesSucceeded */, null /* redirectUrl */);
-        assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
+        assertEquals(0, mRegisteredReceivers.size());
         return nm;
     }
 
     private NetworkMonitor runFailedNetworkTest() throws RemoteException {
         final NetworkMonitor nm = runNetworkTest(
                 VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
-        assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
+        assertEquals(0, mRegisteredReceivers.size());
         return nm;
     }
 
@@ -2982,7 +2710,7 @@
             throws RemoteException {
         final NetworkMonitor nm = runNetworkTest(NETWORK_VALIDATION_RESULT_PARTIAL,
                 probesSucceeded, null /* redirectUrl */);
-        assertCaptivePortalAppReceiverRegistered(false /* isPortal */);
+        assertEquals(0, mRegisteredReceivers.size());
         return nm;
     }
 
@@ -3114,13 +2842,5 @@
     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());
-    }
 }