Snap for 9883729 from f4517274d7c61ec5f53618ff5d2540c6deffac0e to mainline-sdkext-release

Change-Id: I534ab1a205665581e8a3773f3bc178ccb44d93f6
diff --git a/Android.bp b/Android.bp
index 49c011e..8c7253e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -188,6 +188,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "android.net.ipsec.ike.stubs.module_lib",
     ],
     sdk_version: "module_33",
     visibility: ["//visibility:private"],
@@ -216,6 +217,7 @@
         "framework-connectivity",
         "framework-connectivity-t.stubs.module_lib",
         "framework-tethering",
+        "android.net.ipsec.ike.stubs.module_lib"
     ],
     sdk_version: "module_current",
     visibility: ["//visibility:private"],
@@ -243,8 +245,7 @@
         "//packages/modules/Connectivity/Tethering",
         "//packages/modules/Connectivity/service",
         "//packages/modules/Connectivity/service-t",
-        "//packages/modules/Connectivity/tests/cts/net",
-        "//packages/modules/Connectivity/tests/cts/hostside/app",
+        "//packages/modules/Connectivity/tests:__subpackages__",
     ],
 }
 
@@ -266,7 +267,7 @@
         "//packages/modules/Connectivity/Tethering",
         "//packages/modules/Connectivity/service",
         "//packages/modules/Connectivity/service-t",
-        "//packages/modules/Connectivity/tests/cts:__subpackages__",
+        "//packages/modules/Connectivity/tests:__subpackages__",
     ],
 }
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9fe8b1d..aa24b56 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -43,6 +43,10 @@
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     <!-- Signature permission defined in NetworkStackStub -->
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
+    <!-- Used by creating test network -->
+    <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <application
         android:extractNativeLibs="false"
         android:persistent="true"
diff --git a/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java b/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
index 0dcd0db..eaf3847 100644
--- a/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
+++ b/apishim/29/com/android/networkstack/apishim/api29/ConstantsShim.java
@@ -56,6 +56,10 @@
     // Constants defined in android.content.Context
     public static final String NEARBY_SERVICE = "nearby";
 
+    // Constants defined in android.system.OsConstants
+    public static final int IFA_F_MANAGETEMPADDR = 0x100;
+    public static final int IFA_F_NOPREFIXROUTE = 0x200;
+
     /** Compatibility class for {@link CarrierConfigManager}. */
     @RequiresApi(Build.VERSION_CODES.Q)
     /** See {@link CarrierManager#KEY_CARRIER_SUPPORTS_TETHERING_BOOL} */
diff --git a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java
new file mode 100644
index 0000000..46d6e13
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileBuilderShimImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api29;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+
+/**
+ * Implementation of Ikev2VpnProfileBuilderShim for API 29.
+ *
+ * @param <T> type of builder, typically Ikev2VpnProfile.Builder. This is necessary because at
+ *            compile time, shims for older releases will not have access to this class as it
+ *            debuted in SDK30. So the user of the shim has to pass it in.
+ */
+// NOTE: The trick with the formal parameter only works because when this shim was introduced,
+// the stable API already contained the class that the caller needs to pass in; this won't
+// work for a class added in the latest API level.
+@RequiresApi(Build.VERSION_CODES.Q)
+public class Ikev2VpnProfileBuilderShimImpl<T> implements Ikev2VpnProfileBuilderShim<T> {
+}
diff --git a/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java
new file mode 100644
index 0000000..f84999b
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/api29/Ikev2VpnProfileShimImpl.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api29;
+
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
+/**
+ * Implementation of Ikev2VpnProfileShim for API 29.
+ * @param <T> type of profile, typically Ikev2VpnProfile
+ */
+public class Ikev2VpnProfileShimImpl<T> implements Ikev2VpnProfileShim<T> {
+}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java
new file mode 100644
index 0000000..9a24e63
--- /dev/null
+++ b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileBuilderShimImpl.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api30;
+
+import android.net.Ikev2VpnProfile;
+import android.net.ProxyInfo;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * Implementation of Ikev2VpnProfileBuilderShim for API 30.
+ */
+@RequiresApi(Build.VERSION_CODES.R)
+public class Ikev2VpnProfileBuilderShimImpl
+        extends com.android.networkstack.apishim.api29.Ikev2VpnProfileBuilderShimImpl<
+        Ikev2VpnProfile.Builder> {
+    protected final Ikev2VpnProfile.Builder mBuilder;
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull Ikev2VpnProfile.Builder builder) {
+        mBuilder = builder;
+    }
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull String serverAddr,
+            @NonNull String identity) {
+        mBuilder = new Ikev2VpnProfile.Builder(serverAddr, identity);
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @NonNull String serverAddr, @NonNull String identity) {
+        return new Ikev2VpnProfileBuilderShimImpl(serverAddr, identity);
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthPsk(@NonNull byte[] psk) {
+        mBuilder.setAuthPsk(psk);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthUsernamePassword(
+            @NonNull String user, @NonNull String pass, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        mBuilder.setAuthUsernamePassword(user, pass, serverRootCa);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAuthDigitalSignature(
+            @NonNull X509Certificate userCert, @NonNull PrivateKey key,
+            @Nullable X509Certificate serverRootCa) {
+        mBuilder.setAuthDigitalSignature(userCert, key, serverRootCa);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setBypassable(boolean isBypassable) {
+        mBuilder.setBypassable(true);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setProxy(@Nullable ProxyInfo proxy) {
+        mBuilder.setProxy(proxy);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setMaxMtu(int mtu) {
+        mBuilder.setMaxMtu(mtu);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setMetered(boolean isMetered) {
+        mBuilder.setMetered(isMetered);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setAllowedAlgorithms(
+            @NonNull List<String> algorithmNames) {
+        mBuilder.setAllowedAlgorithms(algorithmNames);
+        return this;
+    }
+
+    @Override
+    public Ikev2VpnProfile.Builder getBuilder() {
+        return mBuilder;
+    }
+
+    @Override
+    public Ikev2VpnProfileShim build() {
+        return Ikev2VpnProfileShimImpl.newInstance(mBuilder.build());
+    }
+}
diff --git a/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java
new file mode 100644
index 0000000..389bc44
--- /dev/null
+++ b/apishim/30/com/android/networkstack/apishim/api30/Ikev2VpnProfileShimImpl.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api30;
+
+import android.net.Ikev2VpnProfile;
+
+import androidx.annotation.NonNull;
+
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
+/**
+ * Implementation of Ikev2VpnProfileShim for API 30.
+ */
+// TODO : when API29 is no longer supported, remove the type argument
+public class Ikev2VpnProfileShimImpl extends
+        com.android.networkstack.apishim.api29.Ikev2VpnProfileShimImpl<Ikev2VpnProfile> {
+    protected Ikev2VpnProfile mProfile;
+
+    protected Ikev2VpnProfileShimImpl() {}
+
+    protected Ikev2VpnProfileShimImpl(Ikev2VpnProfile profile) {
+        mProfile = profile;
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    public static Ikev2VpnProfileShim<Ikev2VpnProfile> newInstance(
+            @NonNull Ikev2VpnProfile profile) {
+        return new Ikev2VpnProfileShimImpl(profile);
+    }
+
+    public Ikev2VpnProfile getProfile() {
+        return mProfile;
+    }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java
new file mode 100644
index 0000000..36363ef
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileBuilderShimImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api31;
+
+import android.net.Ikev2VpnProfile;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+/**
+ * Implementation of Ikev2VpnProfileBuilderShim for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S)
+public class Ikev2VpnProfileBuilderShimImpl
+        extends com.android.networkstack.apishim.api30.Ikev2VpnProfileBuilderShimImpl {
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull Ikev2VpnProfile.Builder builder) {
+        super(builder);
+    }
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull String serverAddr,
+            @NonNull String identity) {
+        super(serverAddr, identity);
+    }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java
new file mode 100644
index 0000000..8e0c078
--- /dev/null
+++ b/apishim/31/com/android/networkstack/apishim/api31/Ikev2VpnProfileShimImpl.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.api31;
+
+/**
+ * Implementation of Ikev2VpnProfileShim for API 31.
+ */
+public class Ikev2VpnProfileShimImpl extends
+        com.android.networkstack.apishim.api30.Ikev2VpnProfileShimImpl {
+}
diff --git a/apishim/33/com/android/networkstack/apishim/api33/ConstantsShim.java b/apishim/33/com/android/networkstack/apishim/api33/ConstantsShim.java
index 66714c9..c8b4edd 100644
--- a/apishim/33/com/android/networkstack/apishim/api33/ConstantsShim.java
+++ b/apishim/33/com/android/networkstack/apishim/api33/ConstantsShim.java
@@ -31,6 +31,15 @@
     @VisibleForTesting
     public static final int VERSION = 33;
 
-    // Constants defined in android.app.BroadcastOptions.
+    // Constant defined in android.app.BroadcastOptions.
+    public static final int DELIVERY_GROUP_POLICY_ALL = 0;
+    // Constant defined in android.app.BroadcastOptions.
     public static final int DELIVERY_GROUP_POLICY_MOST_RECENT = 1;
+
+    // Constant defined in android.app.BroadcastOptions.
+    public static final int DEFERRAL_POLICY_DEFAULT = 0;
+    // Constant defined in android.app.BroadcastOptions.
+    public static final int DEFERRAL_POLICY_NONE = 1;
+    // Constant defined in android.app.BroadcastOptions.
+    public static final int DEFERRAL_POLICY_UNTIL_ACTIVE = 2;
 }
diff --git a/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileBuilderShimImpl.java b/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileBuilderShimImpl.java
new file mode 100644
index 0000000..64c7dad
--- /dev/null
+++ b/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileBuilderShimImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.api33;
+
+import android.net.Ikev2VpnProfile;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+/**
+ * A shim for Ikev2VpnProfile.Builder
+ */
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+public class Ikev2VpnProfileBuilderShimImpl
+        extends com.android.networkstack.apishim.api31.Ikev2VpnProfileBuilderShimImpl {
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull IkeTunnelConnectionParams params) {
+        super(new Ikev2VpnProfile.Builder(params));
+    }
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull String serverAddr,
+            @NonNull String identity) {
+        super(serverAddr, identity);
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    @RequiresApi(Build.VERSION_CODES.R)
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @NonNull String serverAddr, @NonNull String identity) {
+        if (SdkLevel.isAtLeastT()) {
+            return new Ikev2VpnProfileBuilderShimImpl(serverAddr, identity);
+        }
+        return com.android.networkstack.apishim.api30.Ikev2VpnProfileBuilderShimImpl
+                .newInstance(serverAddr, identity);
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @NonNull IkeTunnelConnectionParams params) throws UnsupportedApiLevelException {
+        if (SdkLevel.isAtLeastT()) {
+            return new Ikev2VpnProfileBuilderShimImpl(params);
+        } else {
+            throw new UnsupportedApiLevelException("Only supported from API 33");
+        }
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setRequiresInternetValidation(boolean)
+     */
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setRequiresInternetValidation(
+            boolean requiresInternetValidation) {
+        mBuilder.setRequiresInternetValidation(requiresInternetValidation);
+        return this;
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setLocalRoutesExcluded(boolean)
+     */
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> setLocalRoutesExcluded(
+            boolean excludeLocalRoutes) {
+        mBuilder.setLocalRoutesExcluded(excludeLocalRoutes);
+        return this;
+    }
+}
diff --git a/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileShimImpl.java b/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileShimImpl.java
new file mode 100644
index 0000000..6821326
--- /dev/null
+++ b/apishim/33/com/android/networkstack/apishim/api33/Ikev2VpnProfileShimImpl.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.api33;
+
+/**
+ * A shim for Ikev2VpnProfile
+ */
+public class Ikev2VpnProfileShimImpl
+        extends com.android.networkstack.apishim.api30.Ikev2VpnProfileShimImpl {
+}
diff --git a/apishim/34/com/android/networkstack/apishim/BroadcastOptionsShimImpl.java b/apishim/34/com/android/networkstack/apishim/BroadcastOptionsShimImpl.java
index a6c2c44..57359cc 100644
--- a/apishim/34/com/android/networkstack/apishim/BroadcastOptionsShimImpl.java
+++ b/apishim/34/com/android/networkstack/apishim/BroadcastOptionsShimImpl.java
@@ -64,11 +64,11 @@
         return this;
     }
 
-    /** See android.app.BroadcastOptions#setDeferUntilActive */
+    /** See android.app.BroadcastOptions#setDeferralPolicy */
     @Override
-    public BroadcastOptionsShim setDeferUntilActive(boolean shouldDefer)
+    public BroadcastOptionsShim setDeferralPolicy(int deferralPolicy)
             throws UnsupportedApiLevelException {
-        mOptions.setDeferUntilActive(shouldDefer);
+        mOptions.setDeferralPolicy(deferralPolicy);
         return this;
     }
 }
diff --git a/apishim/34/com/android/networkstack/apishim/ConstantsShim.java b/apishim/34/com/android/networkstack/apishim/ConstantsShim.java
index c946544..65f600a 100644
--- a/apishim/34/com/android/networkstack/apishim/ConstantsShim.java
+++ b/apishim/34/com/android/networkstack/apishim/ConstantsShim.java
@@ -18,6 +18,7 @@
 
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.system.OsConstants;
 
 import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
@@ -40,4 +41,8 @@
     // Constants defined in android.content.pm.PackageManager
     public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES =
             PackageManager.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES;
+
+    // Constants defined in android.system.OsConstants
+    public static final int IFA_F_MANAGETEMPADDR = OsConstants.IFA_F_MANAGETEMPADDR;
+    public static final int IFA_F_NOPREFIXROUTE = OsConstants.IFA_F_NOPREFIXROUTE;
 }
diff --git a/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java b/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java
new file mode 100644
index 0000000..470f1b4
--- /dev/null
+++ b/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileBuilderShimImpl.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.Ikev2VpnProfile;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
+import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+
+/**
+ * A shim for Ikev2VpnProfile.Builder
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class Ikev2VpnProfileBuilderShimImpl
+        extends com.android.networkstack.apishim.api33.Ikev2VpnProfileBuilderShimImpl {
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull IkeTunnelConnectionParams params) {
+        super(params);
+    }
+
+    protected Ikev2VpnProfileBuilderShimImpl(@NonNull String serverAddr,
+            @NonNull String identity) {
+        super(serverAddr, identity);
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    @RequiresApi(Build.VERSION_CODES.R)
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @NonNull String serverAddr, @NonNull String identity) {
+        if (SdkLevel.isAtLeastU()) {
+            return new Ikev2VpnProfileBuilderShimImpl(serverAddr, identity);
+        }
+        return com.android.networkstack.apishim.api33.Ikev2VpnProfileBuilderShimImpl
+                .newInstance(serverAddr, identity);
+    }
+
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    public static Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder> newInstance(
+            @NonNull IkeTunnelConnectionParams params) throws UnsupportedApiLevelException {
+        if (SdkLevel.isAtLeastU()) {
+            return new Ikev2VpnProfileBuilderShimImpl(params);
+        } else {
+            return com.android.networkstack.apishim.api33.Ikev2VpnProfileBuilderShimImpl
+                    .newInstance(params);
+        }
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAutomaticIpVersionSelectionEnabled(boolean)
+     */
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder>
+            setAutomaticIpVersionSelectionEnabled(boolean isEnabled) {
+        mBuilder.setAutomaticIpVersionSelectionEnabled(isEnabled);
+        return this;
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAutomaticNattKeepaliveTimerEnabled(boolean)
+     */
+    @Override
+    public Ikev2VpnProfileBuilderShim<Ikev2VpnProfile.Builder>
+            setAutomaticNattKeepaliveTimerEnabled(boolean isEnabled) {
+        mBuilder.setAutomaticNattKeepaliveTimerEnabled(isEnabled);
+        return this;
+    }
+}
diff --git a/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java b/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java
new file mode 100644
index 0000000..cd4a8ca
--- /dev/null
+++ b/apishim/34/com/android/networkstack/apishim/Ikev2VpnProfileShimImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.Ikev2VpnProfile;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
+
+/**
+ * A shim for Ikev2VpnProfile
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class Ikev2VpnProfileShimImpl
+        extends com.android.networkstack.apishim.api30.Ikev2VpnProfileShimImpl {
+    protected Ikev2VpnProfileShimImpl(Ikev2VpnProfile profile) {
+        super(profile);
+    }
+    /**
+     * Returns a new instance of this shim impl.
+     */
+    @RequiresApi(Build.VERSION_CODES.R)
+    public static Ikev2VpnProfileShim<Ikev2VpnProfile> newInstance(Ikev2VpnProfile profile) {
+        if (SdkLevel.isAtLeastU()) {
+            return new Ikev2VpnProfileShimImpl(profile);
+        } else {
+            return com.android.networkstack.apishim.api30.Ikev2VpnProfileShimImpl
+                    .newInstance(profile);
+        }
+    }
+
+    /**
+     * @see Ikev2VpnProfile#isAutomaticIpVersionSelectionEnabled()
+     */
+    public boolean isAutomaticIpVersionSelectionEnabled() {
+        return mProfile.isAutomaticIpVersionSelectionEnabled();
+    }
+
+    /**
+     * @see Ikev2VpnProfile#isAutomaticNattKeepaliveTimerEnabled()
+     */
+    public boolean isAutomaticNattKeepaliveTimerEnabled() {
+        return mProfile.isAutomaticNattKeepaliveTimerEnabled();
+    }
+}
diff --git a/apishim/common/com/android/networkstack/apishim/common/BroadcastOptionsShim.java b/apishim/common/com/android/networkstack/apishim/common/BroadcastOptionsShim.java
index 097270d..ac6b8fb 100644
--- a/apishim/common/com/android/networkstack/apishim/common/BroadcastOptionsShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/BroadcastOptionsShim.java
@@ -37,8 +37,8 @@
         throw new UnsupportedApiLevelException("Only supported starting from API 34");
     }
 
-    /** See android.app.BroadcastOptions#setDeferUntilActive */
-    default BroadcastOptionsShim setDeferUntilActive(boolean shouldDefer)
+    /** See android.app.BroadcastOptions#setDeferralPolicy */
+    default BroadcastOptionsShim setDeferralPolicy(int deferralPolicy)
             throws UnsupportedApiLevelException {
         throw new UnsupportedApiLevelException("Only supported starting from API 34");
     }
diff --git a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java
new file mode 100644
index 0000000..4232885
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileBuilderShim.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.common;
+
+import android.net.ProxyInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * A shim for Ikev2VpnProfile.Builder.
+ *
+ * T should extend Ikev2VpnProfile.Builder, but this can't be written here as that class is not
+ * available in API29.
+ * @param <T> type of builder, typically Ikev2VpnProfile.Builder
+ */
+// TODO : when API29 is no longer supported, remove the type argument
+public interface Ikev2VpnProfileBuilderShim<T> {
+    /**
+     * @see Ikev2VpnProfile.Builder#setRequiresInternetValidation(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setRequiresInternetValidation(
+            boolean requiresInternetValidation) throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 33");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthPsk(byte[])
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthPsk(@NonNull byte[] psk)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthUsernamePassword(String, String, X509Certificate)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthUsernamePassword(@NonNull String user,
+            @NonNull String pass, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAuthDigitalSignature(X509Certificate, PrivateKey,
+     *      X509Certificate)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAuthDigitalSignature(@NonNull X509Certificate userCert,
+            @NonNull PrivateKey key, @Nullable X509Certificate serverRootCa)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setBypassable(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setBypassable(boolean isBypassable)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setProxy(ProxyInfo)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setProxy(@Nullable ProxyInfo proxy)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setMaxMtu(int)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setMaxMtu(int mtu) throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setMetered(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setMetered(boolean isMetered)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAllowedAlgorithms(List<String>)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAllowedAlgorithms(@NonNull List<String> algorithmNames)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setLocalRoutesExcluded(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setLocalRoutesExcluded(boolean excludeLocalRoutes)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 33");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAutomaticIpVersionSelectionEnabled(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAutomaticIpVersionSelectionEnabled(boolean isEnabled)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 34");
+    }
+
+    /**
+     * @see Ikev2VpnProfile.Builder#setAutomaticNattKeepaliveTimerEnabled(boolean)
+     */
+    default Ikev2VpnProfileBuilderShim<T> setAutomaticNattKeepaliveTimerEnabled(boolean isEnabled)
+            throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 34");
+    }
+
+    /**
+     * Get <T> type of builder, typically Ikev2VpnProfile.Builder
+     */
+    default T getBuilder() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+
+    /**
+     * Build an Ikev2VpnProfileShim
+     */
+    default Ikev2VpnProfileShim build() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API 30");
+    }
+}
diff --git a/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java
new file mode 100644
index 0000000..ad0bdcd
--- /dev/null
+++ b/apishim/common/com/android/networkstack/apishim/common/Ikev2VpnProfileShim.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim.common;
+
+/**
+ * A shim for Ikev2VpnProfile.
+ *
+ * T should extend Ikev2VpnProfile, but this can't be written here as that class is not
+ * available in API29.
+ * @param <T> type of profile, typically Ikev2VpnProfile
+ */
+// TODO : when API29 is no longer supported, remove the type argument
+public interface Ikev2VpnProfileShim<T> {
+    /**
+     * @see Ikev2VpnProfile#isAutomaticNattKeepaliveTimerEnabled()
+     */
+    default boolean isAutomaticNattKeepaliveTimerEnabled() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 34.");
+    }
+
+    /**
+     * @see Ikev2VpnProfile#isAutomaticIpVersionSelectionEnabled()
+     */
+    default boolean isAutomaticIpVersionSelectionEnabled() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 34.");
+    }
+    /**
+     * Return the <T> type of profile.
+     * TODO: remove when Q is no longer supported.
+     */
+    default T getProfile() throws UnsupportedApiLevelException {
+        throw new UnsupportedApiLevelException("Only supported from API level 30.");
+    }
+}
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index 89de36b..035ddc7 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -128,30 +128,40 @@
         },
     },
     imports: ["ipmemorystore-aidl-interfaces-V10"],
-    versions: [
-        "1",
-        "2",
-        "3",
-        "4",
-        "5",
-        "6",
-        "7",
-        "8",
-        "9",
-        "10",
-        "11",
-        "12",
-        "13",
-        "14",
-        "15",
-        "16",
-    ],
     // TODO: have tethering depend on networkstack-client and set visibility to private
     visibility: [
         "//system/tools/aidl/build",
         "//frameworks/base/packages/Tethering",
         "//packages/modules/Connectivity/Tethering",
     ],
+    versions_with_info: [
+        // Remove old networkstack aidl interface version info that is no longer used.
+        {
+            version: "13",
+            imports: ["ipmemorystore-aidl-interfaces-V10"],
+        },
+        {
+            version: "14",
+            imports: ["ipmemorystore-aidl-interfaces-V10"],
+        },
+        {
+            version: "15",
+            imports: ["ipmemorystore-aidl-interfaces-V10"],
+        },
+        {
+            version: "16",
+            imports: ["ipmemorystore-aidl-interfaces-V10"],
+        },
+        {
+            version: "17",
+            imports: ["ipmemorystore-aidl-interfaces-V10"],
+        },
+
+    ],
+
+    // "frozen: true" is removed manually after each freeze, this property cannot be unrecognized
+    // in some downstream branches and TH will get the build error, see b/262507066 for details.
+
 }
 
 java_library {
@@ -160,7 +170,7 @@
     min_sdk_version: "29",
     static_libs: [
         "ipmemorystore-aidl-interfaces-V10-java",
-        "networkstack-aidl-interfaces-V16-java",
+        "networkstack-aidl-interfaces-V17-java",
     ],
     visibility: ["//packages/modules/NetworkStack:__subpackages__"],
     apex_available: [
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/.hash b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/.hash
new file mode 100644
index 0000000..a9db7c1
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/.hash
@@ -0,0 +1 @@
+e29ecca6f4e40189d76cf0a1ac6cbc7bccd1db8a
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DataStallReportParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DataStallReportParcelable.aidl
new file mode 100644
index 0000000..771deda
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DataStallReportParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DataStallReportParcelable {
+  long timestampMillis = 0;
+  int detectionMethod = 1;
+  int tcpPacketFailRate = 2;
+  int tcpMetricsCollectionPeriodMillis = 3;
+  int dnsConsecutiveTimeouts = 4;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31f2194
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable DhcpResultsParcelable {
+  android.net.StaticIpConfiguration baseConfiguration;
+  int leaseDuration;
+  int mtu;
+  String serverAddress;
+  String vendorInfo;
+  @nullable String serverHostName;
+  @nullable String captivePortalApiUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..fb13c0c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitor.aidl
@@ -0,0 +1,60 @@
+/**
+ * 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);
+  oneway void notifyNetworkConnectedParcel(in android.net.networkstack.aidl.NetworkMonitorParameters params);
+  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 = 0x01;
+  const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+  const int NETWORK_VALIDATION_RESULT_SKIPPED = 0x04;
+  const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+  const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+  const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+  const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+  const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..36eda8e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkMonitorCallbacks {
+  oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor) = 0;
+  oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl) = 1;
+  oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config) = 2;
+  oneway void showProvisioningNotification(String action, String packageName) = 3;
+  oneway void hideProvisioningNotification() = 4;
+  oneway void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) = 5;
+  oneway void notifyNetworkTestedWithExtras(in android.net.NetworkTestResultParcelable result) = 6;
+  oneway void notifyDataStallSuspected(in android.net.DataStallReportParcelable report) = 7;
+  oneway void notifyCaptivePortalDataChanged(in android.net.CaptivePortalData data) = 8;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..8120ffc
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackConnector {
+  oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+  oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+  oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+  oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+  oneway void allowTestUid(int uid, in android.net.INetworkStackStatusCallback cb);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..0b6b778
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetworkStackStatusCallback {
+  oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InformationElementParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InformationElementParcelable.aidl
new file mode 100644
index 0000000..6103774
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InformationElementParcelable.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InformationElementParcelable {
+  int id;
+  byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..6a597e6
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable InitialConfigurationParcelable {
+  android.net.LinkAddress[] ipAddresses;
+  android.net.IpPrefix[] directlyConnectedRoutes;
+  String[] dnsServers;
+  String gateway;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2InformationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2InformationParcelable.aidl
new file mode 100644
index 0000000..83796ee
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2InformationParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2InformationParcelable {
+  String l2Key;
+  String cluster;
+  android.net.MacAddress bssid;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2PacketParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2PacketParcelable.aidl
new file mode 100644
index 0000000..4b3fff5
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/Layer2PacketParcelable.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable Layer2PacketParcelable {
+  android.net.MacAddress dstMacAddress;
+  byte[] payload;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..18cf954
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NattKeepalivePacketDataParcelable {
+  byte[] srcAddress;
+  int srcPort;
+  byte[] dstAddress;
+  int dstPort;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NetworkTestResultParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NetworkTestResultParcelable.aidl
new file mode 100644
index 0000000..4d6d5a2
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/NetworkTestResultParcelable.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable NetworkTestResultParcelable {
+  long timestampMillis;
+  int result;
+  int probesSucceeded;
+  int probesAttempted;
+  String redirectUrl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..1457caf
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable PrivateDnsConfigParcel {
+  String hostname;
+  String[] ips;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..fba524b
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,63 @@
+/*
+**
+** 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;
+  boolean uniqueEui64AddressesOnly;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ScanResultInfoParcelable.aidl
new file mode 100644
index 0000000..94fc27f
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ScanResultInfoParcelable.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable ScanResultInfoParcelable {
+  String ssid;
+  String bssid;
+  android.net.InformationElementParcelable[] informationElements;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..0e1c21c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+@JavaDerive(toString=true)
+parcelable TcpKeepalivePacketDataParcelable {
+  byte[] srcAddress;
+  int srcPort;
+  byte[] dstAddress;
+  int dstPort;
+  int seq;
+  int ack;
+  int rcvWnd;
+  int rcvWndScale;
+  int tos;
+  int ttl;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpLeaseParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpLeaseParcelable.aidl
new file mode 100644
index 0000000..3cd8860
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpLeaseParcelable.aidl
@@ -0,0 +1,43 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpLeaseParcelable {
+  byte[] clientId;
+  byte[] hwAddr;
+  int netAddr;
+  int prefixLength;
+  long expTime;
+  String hostname;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..7997936
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,49 @@
+/**
+ *
+ * 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;
+  int leasesSubnetPrefixLength = 0;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpEventCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpEventCallbacks.aidl
new file mode 100644
index 0000000..9312f47
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpEventCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+interface IDhcpEventCallbacks {
+  oneway void onLeasesChanged(in List<android.net.dhcp.DhcpLeaseParcelable> newLeases);
+  oneway void onNewPrefixRequest(in android.net.IpPrefix currentPrefix);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..1109f35
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServer {
+  oneway void start(in android.net.INetworkStackStatusCallback cb) = 0;
+  oneway void startWithCallbacks(in android.net.INetworkStackStatusCallback statusCb, in android.net.dhcp.IDhcpEventCallbacks eventCb) = 3;
+  oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb) = 1;
+  oneway void stop(in android.net.INetworkStackStatusCallback cb) = 2;
+  const int STATUS_UNKNOWN = 0;
+  const int STATUS_SUCCESS = 1;
+  const int STATUS_INVALID_ARGUMENT = 2;
+  const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..ab8577c
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+/* @hide */
+interface IDhcpServerCallbacks {
+  oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..3ba1d0b
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClient.aidl
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+/* @hide */
+interface IIpClient {
+  oneway void completedPreDhcpAction();
+  oneway void confirmConfiguration();
+  oneway void readPacketFilterComplete(in byte[] data);
+  oneway void shutdown();
+  oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+  oneway void stop();
+  oneway void setTcpBufferSizes(in String tcpBufferSizes);
+  oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+  oneway void setMulticastFilter(boolean enabled);
+  oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+  oneway void removeKeepalivePacketFilter(int slot);
+  oneway void setL2KeyAndGroupHint(in String l2Key, in String cluster);
+  oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+  oneway void notifyPreconnectionComplete(boolean success);
+  oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info);
+  const int PROV_IPV4_DISABLED = 0x00;
+  const int PROV_IPV4_STATIC = 0x01;
+  const int PROV_IPV4_DHCP = 0x02;
+  const int PROV_IPV6_DISABLED = 0x00;
+  const int PROV_IPV6_SLAAC = 0x01;
+  const int PROV_IPV6_LINKLOCAL = 0x02;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..9d36419
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing 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);
+  oneway void onReachabilityFailure(in android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable lossInfo);
+  oneway void setMaxDtimMultiplier(int multiplier);
+  const int DTIM_MULTIPLIER_RESET = 0;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/NetworkMonitorParameters.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/NetworkMonitorParameters.aidl
new file mode 100644
index 0000000..2ab9db0
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/NetworkMonitorParameters.aidl
@@ -0,0 +1,41 @@
+/**
+ *
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.networkstack.aidl;
+@JavaDerive(equals=true, toString=true)
+parcelable NetworkMonitorParameters {
+  android.net.NetworkAgentConfig networkAgentConfig;
+  android.net.NetworkCapabilities networkCapabilities;
+  android.net.LinkProperties linkProperties;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/dhcp/DhcpOption.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
new file mode 100644
index 0000000..eea3e0d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/dhcp/DhcpOption.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.networkstack.aidl.dhcp;
+@JavaDerive(toString=true)
+parcelable DhcpOption {
+  byte type;
+  @nullable byte[] value;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl
new file mode 100644
index 0000000..bb88434
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.ip;
+@JavaDerive(equals=true, toString=true) @JavaOnlyImmutable
+parcelable ReachabilityLossInfoParcelable {
+  String message;
+  android.net.networkstack.aidl.ip.ReachabilityLossReason reason;
+}
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
new file mode 100644
index 0000000..f9bb3c4
--- /dev/null
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/17/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.ip;
+@Backing(type="int")
+enum ReachabilityLossReason {
+  ROAM,
+  CONFIRM,
+  ORGANIC,
+}
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 fc6a70e..fb13c0c 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
@@ -49,12 +49,12 @@
   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;
+  const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
+  const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+  const int NETWORK_VALIDATION_RESULT_SKIPPED = 0x04;
+  const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+  const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+  const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+  const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+  const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
 }
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..3ba1d0b 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
@@ -49,10 +49,10 @@
   oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
   oneway void notifyPreconnectionComplete(boolean success);
   oneway void updateLayer2Information(in android.net.Layer2InformationParcelable info);
-  const int PROV_IPV4_DISABLED = 0;
-  const int PROV_IPV4_STATIC = 1;
-  const int PROV_IPV4_DHCP = 2;
-  const int PROV_IPV6_DISABLED = 0;
-  const int PROV_IPV6_SLAAC = 1;
-  const int PROV_IPV6_LINKLOCAL = 2;
+  const int PROV_IPV4_DISABLED = 0x00;
+  const int PROV_IPV4_STATIC = 0x01;
+  const int PROV_IPV4_DHCP = 0x02;
+  const int PROV_IPV6_DISABLED = 0x00;
+  const int PROV_IPV6_SLAAC = 0x01;
+  const int PROV_IPV6_LINKLOCAL = 0x02;
 }
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 24bbf64..9d36419 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
@@ -49,4 +49,6 @@
   oneway void setNeighborDiscoveryOffload(boolean enable);
   oneway void onPreconnectionStart(in List<android.net.Layer2PacketParcelable> packets);
   oneway void onReachabilityFailure(in android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable lossInfo);
+  oneway void setMaxDtimMultiplier(int multiplier);
+  const int DTIM_MULTIPLIER_RESET = 0;
 }
diff --git a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
index 70a7db2..f9bb3c4 100644
--- a/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
+++ b/common/networkstackclient/aidl_api/networkstack-aidl-interfaces/current/android/net/networkstack/aidl/ip/ReachabilityLossReason.aidl
@@ -34,7 +34,7 @@
 package android.net.networkstack.aidl.ip;
 @Backing(type="int")
 enum ReachabilityLossReason {
-  ROAM = 0,
-  CONFIRM = 1,
-  ORGANIC = 2,
+  ROAM,
+  CONFIRM,
+  ORGANIC,
 }
diff --git a/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl
index 932672e..5bb0cf3 100644
--- a/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl
+++ b/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl
@@ -72,4 +72,20 @@
     // Called when the internal IpReachabilityMonitor (if enabled) has detected the loss of a
     // critical number of required neighbors or DHCP roaming fails.
     void onReachabilityFailure(in ReachabilityLossInfoParcelable lossInfo);
+
+    // Reset the DTIM multiplier to the default hardware driver value.
+    const int DTIM_MULTIPLIER_RESET = 0;
+
+    // Set maximum acceptable DTIM multiplier to hardware driver. Any multiplier larger than the
+    // maximum value must not be accepted, it will cause packet loss higher than what the system
+    // can accept, which will cause unexpected behavior for apps, and may interrupt the network
+    // connection.
+    //
+    // DTIM multiplier controls how often the device should wake up to receive multicast/broadcast
+    // packets. Typically the wake up interval is decided by multiplier * AP's DTIM period if
+    // multiplier is non-zero. For example, when hardware driver sets the DTIM multiplier to 2, it
+    // means device wakes up once every 2 DTIM periods, 50% of multicast packets will be dropped.
+    // Setting DTIM multiplier to DTIM_MULTIPLIER_RESET(0) applies the hardware driver default
+    // value.
+    void setMaxDtimMultiplier(int multiplier);
 }
diff --git a/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
index 7cf46f5..e46d4c9 100644
--- a/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
+++ b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
@@ -146,4 +146,11 @@
         // onReachabilityLost method.
         onReachabilityLost(lossInfo.message);
     }
+
+    /**
+     * Set maximum acceptable DTIM multiplier to hardware driver.
+     *
+     * @param multiplier an integer maximum DTIM multiplier value to set.
+     */
+    public void setMaxDtimMultiplier(int multiplier) {}
 }
diff --git a/common/networkstackclient/src/android/net/ip/IpClientUtil.java b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
index 7636abd..b953d35 100644
--- a/common/networkstackclient/src/android/net/ip/IpClientUtil.java
+++ b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
@@ -198,6 +198,12 @@
             mCb.onReachabilityFailure(lossInfo);
         }
 
+        // Set maximum acceptable DTIM multiplier to hardware driver.
+        @Override
+        public void setMaxDtimMultiplier(int multiplier) {
+            mCb.setMaxDtimMultiplier(multiplier);
+        }
+
         @Override
         public int getInterfaceVersion() {
             return this.VERSION;
diff --git a/src/android/net/dhcp6/Dhcp6Packet.java b/src/android/net/dhcp6/Dhcp6Packet.java
new file mode 100644
index 0000000..13d4b80
--- /dev/null
+++ b/src/android/net/dhcp6/Dhcp6Packet.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.dhcp6;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Defines basic data and operations needed to build and use packets for the
+ * DHCPv6 protocol. Subclasses create the specific packets used at each
+ * stage of the negotiation.
+ *
+ * @hide
+ */
+public class Dhcp6Packet {
+
+    /**
+     * DHCPv6 Message Type.
+     */
+    public static final byte DHCP6_MESSAGE_TYPE_SOLICIT = 1;
+    public static final byte DHCP6_MESSAGE_TYPE_ADVERTISE = 2;
+    public static final byte DHCP6_MESSAGE_TYPE_REQUEST = 3;
+    public static final byte DHCP6_MESSAGE_TYPE_CONFIRM = 4;
+    public static final byte DHCP6_MESSAGE_TYPE_RENEW = 5;
+    public static final byte DHCP6_MESSAGE_TYPE_REBIND = 6;
+    public static final byte DHCP6_MESSAGE_TYPE_REPLY = 7;
+    public static final byte DHCP6_MESSAGE_TYPE_RELEASE = 8;
+    public static final byte DHCP6_MESSAGE_TYPE_DECLINE = 9;
+    public static final byte DHCP6_MESSAGE_TYPE_RECONFIGURE = 10;
+    public static final byte DHCP6_MESSAGE_TYPE_INFORMATION_REQUEST = 11;
+    public static final byte DHCP6_MESSAGE_TYPE_RELAY_FORW = 12;
+    public static final byte DHCP6_MESSAGE_TYPE_RELAY_REPL = 13;
+
+    /**
+     * DHCPv6 Optional Type: Client Identifier.
+     * DHCPv6 message from client must have this option.
+     */
+    public static final byte DHCP6_CLIENT_IDENTIFIER = 1;
+    @NonNull
+    protected final byte[] mClientDuid;
+
+    /**
+     * DHCPv6 Optional Type: Server Identifier.
+     */
+    public static final byte DHCP6_SERVER_IDENTIFIER = 2;
+    protected final byte[] mServerDuid;
+
+    /**
+     * DHCPv6 Optional Type: Elapsed time.
+     */
+    public static final byte DHCP6_ELAPSED_TIME = 8;
+    protected final short mSecs;
+
+    /**
+     * DHCPv6 Optional Type: Status Code.
+     */
+    public static final byte DHCP6_STATUS_CODE = 13;
+    protected short mStatusCode;
+    protected String mStatusMsg;
+
+    public static final short STATUS_SUCCESS           = 0;
+    public static final short STATUS_UNSPEC_FAIL       = 1;
+    public static final short STATUS_NO_ADDR_AVAI      = 2;
+    public static final short STATUS_NO_BINDING        = 3;
+    public static final short STATUS_PREFIX_NOT_ONLINK = 4;
+    public static final short STATUS_USE_MULTICAST     = 5;
+    public static final short STATUS_NO_PREFIX_AVAI    = 6;
+
+    /**
+     * DHCPv6 Optional Type: IA_PD.
+     */
+    public static final byte DHCP6_IA_PD = 25;
+    @NonNull
+    protected final byte[] mIaPd;
+
+    /**
+     * The transaction identifier used in this particular DHCPv6 negotiation
+     */
+    protected final int mTransId;
+
+    /**
+     * The unique identifier for IA_NA, IA_TA, IA_PD used in this particular DHCPv6 negotiation
+     */
+    protected int mIaId;
+
+    Dhcp6Packet(int transId, short secs, @NonNull final byte[] clientDuid, final byte[] serverDuid,
+            @NonNull final byte[] iapd) {
+        mTransId = transId;
+        mSecs = secs;
+        mClientDuid = clientDuid;
+        mServerDuid = serverDuid;
+        mIaPd = iapd;
+    }
+
+    /**
+     * Returns the transaction ID.
+     */
+    public int getTransactionId() {
+        return mTransId;
+    }
+
+    /**
+     * Returns IA_ID associated to IA_PD.
+     */
+    public int getIaId() {
+        return mIaId;
+    }
+
+    /**
+     * Returns the client's DUID.
+     */
+    @NonNull
+    public byte[] getClientDuid() {
+        return mClientDuid;
+    }
+
+    /**
+     * Returns the server's DUID.
+     */
+    public byte[] getServerDuid() {
+        return mServerDuid;
+    }
+}
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index fa03e08..5cd56ae 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -432,6 +432,18 @@
         }
 
         /**
+         * Set maximum acceptable DTIM multiplier to hardware driver.
+         */
+        public void setMaxDtimMultiplier(int multiplier) {
+            log("setMaxDtimMultiplier(" + multiplier + ")");
+            try {
+                mCallback.setMaxDtimMultiplier(multiplier);
+            } catch (RemoteException e) {
+                log("Failed to call setMaxDtimMultiplier", e);
+            }
+        }
+
+        /**
          * Get the version of the IIpClientCallbacks AIDL interface.
          */
         public int getInterfaceVersion() {
diff --git a/src/com/android/networkstack/util/NetworkStackUtils.java b/src/com/android/networkstack/util/NetworkStackUtils.java
index 5c072de..296141e 100755
--- a/src/com/android/networkstack/util/NetworkStackUtils.java
+++ b/src/com/android/networkstack/util/NetworkStackUtils.java
@@ -17,6 +17,7 @@
 package com.android.networkstack.util;
 
 import android.content.Context;
+import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.MacAddress;
 import android.system.ErrnoException;
@@ -26,6 +27,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.net.module.util.DeviceConfigUtils;
+import com.android.net.module.util.HexDump;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -326,6 +328,47 @@
     }
 
     /**
+     * Convert 48bits MAC address to 64bits link-layer address(EUI64).
+     *     1. insert the 0xFFFE in the middle of mac address
+     *     2. flip the 7th bit(universal/local) of the first byte.
+     */
+    public static byte[] macAddressToEui64(@NonNull final MacAddress hwAddr) {
+        final byte[] eui64 = new byte[8];
+        final byte[] mac48 = hwAddr.toByteArray();
+        System.arraycopy(mac48 /* src */, 0 /* srcPos */, eui64 /* dest */, 0 /* destPos */,
+                3 /* length */);
+        eui64[3] = (byte) 0xFF;
+        eui64[4] = (byte) 0xFE;
+        System.arraycopy(mac48 /* src */, 3 /* srcPos */, eui64 /* dest */, 5 /* destPos */,
+                3 /* length */);
+        eui64[0] = (byte) (eui64[0] ^ 0x02); // flip 7th bit
+        return eui64;
+    }
+
+    /**
+     * Generate an IPv6 address based on the given prefix(/64) and stable interface
+     * identifier(EUI64).
+     */
+    public static Inet6Address createInet6AddressFromEui64(@NonNull final IpPrefix prefix,
+            @NonNull final byte[] eui64) {
+        if (prefix.getPrefixLength() != 64) {
+            Log.e(TAG, "Invalid IPv6 prefix length " + prefix.getPrefixLength());
+            return null;
+        }
+        final byte[] address = new byte[16];
+        System.arraycopy(prefix.getRawAddress() /* src */, 0 /* srcPos */, address /* dest */,
+                0 /* destPos*/, 8 /* length */);
+        System.arraycopy(eui64 /* src */, 0 /* srcPos */, address /* dest */, 8 /* destPos */,
+                eui64.length);
+        try {
+            return (Inet6Address) InetAddress.getByAddress(address);
+        } catch (UnknownHostException e) {
+            Log.e(TAG, "Invalid IPv6 address " + HexDump.toHexString(address), e);
+            return null;
+        }
+    }
+
+    /**
      * Attaches a socket filter that accepts DHCP packets to the given socket.
      */
     public static native void attachDhcpFilter(FileDescriptor fd, boolean dropMF)
diff --git a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
index e36af57..c9c0e01 100644
--- a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
@@ -640,6 +640,10 @@
         }
 
         mIIpClient = makeIIpClient(mIfaceName, mCb);
+
+        // Enable multicast filtering after creating IpClient instance, make the integration test
+        // more realistic.
+        mIIpClient.setMulticastFilter(true);
     }
 
     protected void setUpMocks() throws Exception {
@@ -979,7 +983,7 @@
 
         startIpClientProvisioning(prov.build());
         if (!isPreconnectionEnabled) {
-            verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+            verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
         }
         verify(mCb, never()).onProvisioningFailure(any());
     }
@@ -1287,7 +1291,7 @@
                 mDependencies.mDhcpClient.sendMessage(DhcpClient.CMD_TIMEOUT);
             }
         }
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
 
         final LinkAddress ipAddress = new LinkAddress(CLIENT_ADDR, PREFIX_LENGTH);
         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetCfg(ifConfig.capture());
@@ -2352,7 +2356,7 @@
         // Force IpClient transition to RunningState from PreconnectionState.
         mIIpClient.notifyPreconnectionComplete(false /* success */);
         HandlerUtils.waitForIdle(mDependencies.mDhcpClient.getHandler(), TEST_TIMEOUT_MS);
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
     }
 
     @Test
@@ -3063,7 +3067,7 @@
         // Force IpClient transition to RunningState from PreconnectionState.
         mIpc.notifyPreconnectionComplete(true /* success */);
         HandlerUtils.waitForIdle(mDependencies.mDhcpClient.getHandler(), TEST_TIMEOUT_MS);
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
 
         // DHCP server SHOULD NOT honor the Rapid-Commit option if the response would
         // contain the IPv6-only Preferred option to the client, instead respond with
@@ -3246,7 +3250,7 @@
                 false /* isDhcpIpConflictDetectEnabled */, false /* isIPv6OnlyPreferredEnabled */);
 
         startIpClientProvisioning(prov.build());
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
         verify(mCb, never()).onProvisioningFailure(any());
 
         return getNextDhcpPacket();
@@ -3798,7 +3802,7 @@
         setFeatureEnabled(NetworkStackUtils.IP_REACHABILITY_MCAST_RESOLICIT_VERSION,
                 isMulticastResolicitEnabled);
         startIpClientProvisioning(config);
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
         doIpv6OnlyProvisioning();
 
         // Simulate the roaming.
@@ -3957,7 +3961,7 @@
         final ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                 .build();
         startIpClientProvisioning(config);
-        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
+        verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(true);
 
         final List<ByteBuffer> options = new ArrayList<ByteBuffer>();
         options.add(buildPioOption(3600, 1800, "2001:db8:1::/64")); // PIO
diff --git a/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt b/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt
new file mode 100644
index 0000000..f1cbd21
--- /dev/null
+++ b/tests/integration/signature/android/net/NetworkStatsIntegrationTest.kt
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed 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.Manifest.permission.MANAGE_TEST_NETWORKS
+import android.app.usage.NetworkStats
+import android.app.usage.NetworkStats.Bucket.TAG_NONE
+import android.app.usage.NetworkStatsManager
+import android.net.NetworkTemplate.MATCH_TEST
+import android.os.Process
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.testutils.PacketBridge
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
+import com.android.testutils.TestDnsServer
+import com.android.testutils.TestHttpServer
+import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.runAsShell
+import fi.iki.elonen.NanoHTTPD
+import java.io.BufferedInputStream
+import java.io.BufferedOutputStream
+import java.net.HttpURLConnection
+import java.net.HttpURLConnection.HTTP_OK
+import java.net.InetSocketAddress
+import java.net.URL
+import java.nio.charset.Charset
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class NetworkStatsIntegrationTest {
+    private val INTERNAL_V6ADDR =
+        LinkAddress(InetAddresses.parseNumericAddress("2001:db8::1234"), 64)
+    private val EXTERNAL_V6ADDR =
+        LinkAddress(InetAddresses.parseNumericAddress("2001:db8::5678"), 64)
+
+    // Remote address, both the client and server will have a hallucination that
+    // they are talking to this address.
+    private val REMOTE_V6ADDR =
+        LinkAddress(InetAddresses.parseNumericAddress("dead:beef::808:808"), 64)
+    private val REMOTE_V4ADDR =
+        LinkAddress(InetAddresses.parseNumericAddress("8.8.8.8"), 32)
+    private val DEFAULT_BUFFER_SIZE = 1000
+    private val CONNECTION_TIMEOUT_MILLIS = 15000
+    private val TEST_DOWNLOAD_SIZE = 10000L
+    private val TEST_UPLOAD_SIZE = 20000L
+    private val HTTP_SERVER_NAME = "test.com"
+    private val DNS_SERVER_PORT = 53
+    private val TEST_TAG = 0xF00D
+
+    // Set up the packet bridge with two IPv6 address only test networks.
+    private val inst = InstrumentationRegistry.getInstrumentation()
+    private val context = inst.getContext()
+    private val packetBridge = runAsShell(MANAGE_TEST_NETWORKS) {
+        PacketBridge(context, INTERNAL_V6ADDR, EXTERNAL_V6ADDR, REMOTE_V6ADDR.address)
+    }.apply {
+        start()
+    }
+
+    // Set up DNS server for testing server and DNS64.
+    private val fakeDns = TestDnsServer(
+        packetBridge.externalNetwork, InetSocketAddress(EXTERNAL_V6ADDR.address, DNS_SERVER_PORT)
+    ).apply {
+        start()
+        setAnswer(
+            "ipv4only.arpa",
+            listOf(IpPrefix(REMOTE_V6ADDR.address, REMOTE_V6ADDR.prefixLength).address)
+        )
+        setAnswer(HTTP_SERVER_NAME, listOf(REMOTE_V4ADDR.address))
+    }
+
+    // Start up test http server.
+    private val httpServer = TestHttpServer(EXTERNAL_V6ADDR.address.hostAddress).apply {
+        start()
+    }
+
+    @After
+    fun tearDown() {
+        packetBridge.stop()
+        fakeDns.stop()
+        httpServer.stop()
+    }
+
+    private fun waitFor464XlatReady(network: Network): String {
+        val cm = context.getSystemService(ConnectivityManager::class.java)
+        val iface = cm.getLinkProperties(network).interfaceName
+
+        // Make a network request to listen to the specific test network.
+        val nr = NetworkRequest.Builder()
+            .clearCapabilities()
+            .addTransportType(NetworkCapabilities.TRANSPORT_TEST)
+            .setNetworkSpecifier(TestNetworkSpecifier(iface))
+            .build()
+        val testCb = TestableNetworkCallback()
+        cm.registerNetworkCallback(nr, testCb)
+        // Wait for the stacked address to be available.
+        testCb.eventuallyExpect<LinkPropertiesChanged> {
+            it.lp.stackedLinks?.getOrNull(0)?.linkAddresses?.getOrNull(0) != null
+        }
+        return iface
+    }
+
+    /**
+     * Verify data usage download stats with test 464xlat networks.
+     *
+     * This test starts two test networks and binds them together, the internal one is for the
+     * client to make http traffic on the test network, and the external one is for the mocked
+     * http and dns server to bind to and provide responses.
+     *
+     * After Clat setup, the client will use clat v4 address to send packets to the mocked
+     * server v4 address, which will be translated into a v6 packet by the clat daemon with
+     * NAT64 prefix learned from the mocked DNS64 response. And send to the interface.
+     *
+     * While the packets are being forwarded to the external interface, the servers will see
+     * the packets originated from the mocked v6 address, and destined to a local v6 address.
+     */
+    @Test
+    fun test464XlatTcpStats() {
+        // Wait for 464Xlat to be ready.
+        val internalInterfaceName = waitFor464XlatReady(packetBridge.internalNetwork)
+
+        val (_, rxBytesBeforeTest) = getTotalTxRxBytes(internalInterfaceName)
+        val (_, rxTaggedBytesBeforeTest) = getTaggedTxRxBytes(internalInterfaceName, TEST_TAG)
+
+        // Generate the download traffic.
+        genHttpTraffic(packetBridge.internalNetwork, uploadSize = 0L, TEST_DOWNLOAD_SIZE)
+
+        // In practice, for one way 10k download payload, the download usage is about
+        // 11222~12880 bytes. And the upload usage is about 1279~1626 bytes, which is majorly
+        // contributed by TCP ACK packets.
+        val (txBytesAfterDownload, rxBytesAfterDownload) =
+            getTotalTxRxBytes(internalInterfaceName)
+        val (txTaggedBytesAfterDownload, rxTaggedBytesAfterDownload) = getTaggedTxRxBytes(
+            internalInterfaceName,
+            TEST_TAG
+        )
+        assertInRange(
+            "Download size", internalInterfaceName,
+            rxBytesAfterDownload - rxBytesBeforeTest,
+            TEST_DOWNLOAD_SIZE, (TEST_DOWNLOAD_SIZE * 1.3).toLong()
+        )
+        // Increment of tagged data should be zero since no tagged traffic was generated.
+        assertEquals(
+            rxTaggedBytesBeforeTest,
+            rxTaggedBytesAfterDownload,
+            "Tagged download size of uid ${Process.myUid()} on $internalInterfaceName"
+        )
+
+        // Generate upload traffic with tag to verify tagged data accounting as well.
+        genHttpTrafficWithTag(
+            packetBridge.internalNetwork,
+            TEST_UPLOAD_SIZE,
+            downloadSize = 0L,
+            TEST_TAG
+        )
+
+        // Verify upload data usage accounting.
+        val (txBytesAfterUpload, _) = getTotalTxRxBytes(internalInterfaceName)
+        val (txTaggedBytesAfterUpload, _) = getTaggedTxRxBytes(internalInterfaceName, TEST_TAG)
+        assertInRange(
+            "Upload size", internalInterfaceName,
+            txBytesAfterUpload - txBytesAfterDownload,
+            TEST_UPLOAD_SIZE, (TEST_UPLOAD_SIZE * 1.3).toLong()
+        )
+        assertInRange(
+            "Tagged upload size of uid ${Process.myUid()}",
+            internalInterfaceName,
+            txTaggedBytesAfterUpload - txTaggedBytesAfterDownload,
+            TEST_UPLOAD_SIZE,
+            (TEST_UPLOAD_SIZE * 1.3).toLong()
+        )
+    }
+
+    private fun genHttpTraffic(network: Network, uploadSize: Long, downloadSize: Long) =
+        genHttpTrafficWithTag(network, uploadSize, downloadSize, NetworkStats.Bucket.TAG_NONE)
+
+    private fun genHttpTrafficWithTag(
+        network: Network,
+        uploadSize: Long,
+        downloadSize: Long,
+        tag: Int
+    ) {
+        val path = "/test_upload_download"
+        val buf = ByteArray(DEFAULT_BUFFER_SIZE)
+
+        httpServer.addResponse(
+            TestHttpServer.Request(path, NanoHTTPD.Method.POST), NanoHTTPD.Response.Status.OK,
+            content = getRandomString(downloadSize)
+        )
+        var httpConnection: HttpURLConnection? = null
+        try {
+            TrafficStats.setThreadStatsTag(tag)
+            val spec = "http://$HTTP_SERVER_NAME:${httpServer.listeningPort}$path"
+            val url = URL(spec)
+            httpConnection = network.openConnection(url) as HttpURLConnection
+            httpConnection.connectTimeout = CONNECTION_TIMEOUT_MILLIS
+            httpConnection.requestMethod = "POST"
+            httpConnection.doOutput = true
+            // Tell the server that the response should not be compressed. Otherwise, the data usage
+            // accounted will be less than expected.
+            httpConnection.setRequestProperty("Accept-Encoding", "identity")
+            // Tell the server that to close connection after this request, this is needed to
+            // prevent from reusing the same socket that has different tagging requirement.
+            httpConnection.setRequestProperty("Connection", "close")
+
+            // Send http body.
+            val outputStream = BufferedOutputStream(httpConnection.outputStream)
+            outputStream.write(getRandomString(uploadSize).toByteArray(Charset.forName("UTF-8")))
+            outputStream.close()
+            assertEquals(HTTP_OK, httpConnection.responseCode)
+
+            // Receive response from the server.
+            val inputStream = BufferedInputStream(httpConnection.getInputStream())
+            var total = 0L
+            while (true) {
+                val count = inputStream.read(buf)
+                if (count == -1) break // End-of-Stream
+                total += count
+            }
+            assertEquals(downloadSize, total)
+        } finally {
+            httpConnection?.inputStream?.close()
+            TrafficStats.clearThreadStatsTag()
+        }
+    }
+
+    private fun getTotalTxRxBytes(iface: String): Pair<Long, Long> {
+        return getNetworkStatsThat(iface, TAG_NONE) { nsm, template ->
+            nsm.querySummary(template, Long.MIN_VALUE, Long.MAX_VALUE)
+        }
+    }
+
+    private fun getTaggedTxRxBytes(iface: String, tag: Int): Pair<Long, Long> {
+        return getNetworkStatsThat(iface, tag) { nsm, template ->
+            nsm.queryTaggedSummary(template, Long.MIN_VALUE, Long.MAX_VALUE)
+        }
+    }
+
+    private fun getNetworkStatsThat(
+        iface: String,
+        tag: Int,
+        queryApi: (nsm: NetworkStatsManager, template: NetworkTemplate) -> NetworkStats
+    ): Pair<Long, Long> {
+        val nsm = context.getSystemService(NetworkStatsManager::class.java)
+        nsm.forceUpdate()
+        val testTemplate = NetworkTemplate.Builder(MATCH_TEST)
+            .setWifiNetworkKeys(setOf(iface)).build()
+        val stats = queryApi.invoke(nsm, testTemplate)
+        val recycled = NetworkStats.Bucket()
+        var rx = 0L
+        var tx = 0L
+        while (stats.hasNextBucket()) {
+            stats.getNextBucket(recycled)
+            if (recycled.uid != Process.myUid() || recycled.tag != tag) continue
+            rx += recycled.rxBytes
+            tx += recycled.txBytes
+        }
+        return tx to rx
+    }
+
+    /** Verify the given value is in range [lower, upper]  */
+    private fun assertInRange(tag: String, iface: String, value: Long, lower: Long, upper: Long) =
+        assertTrue(
+            value in lower..upper,
+            "$tag on $iface: $value is not within range [$lower, $upper]"
+        )
+
+    fun getRandomString(length: Long): String {
+        val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
+        return (1..length)
+            .map { allowedChars.random() }
+            .joinToString("")
+    }
+}
diff --git a/tests/integration/signature/android/net/util/NetworkStackUtilsIntegrationTest.kt b/tests/integration/signature/android/net/util/NetworkStackUtilsIntegrationTest.kt
index 0a80d70..d40ea7d 100644
--- a/tests/integration/signature/android/net/util/NetworkStackUtilsIntegrationTest.kt
+++ b/tests/integration/signature/android/net/util/NetworkStackUtilsIntegrationTest.kt
@@ -47,9 +47,9 @@
 import com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN
 import com.android.net.module.util.NetworkStackConstants.IPV4_ADDR_ANY
 import com.android.net.module.util.NetworkStackConstants.IPV4_CHECKSUM_OFFSET
+import com.android.net.module.util.NetworkStackConstants.IPV4_FLAGS_OFFSET
 import com.android.net.module.util.NetworkStackConstants.IPV4_FLAG_DF
 import com.android.net.module.util.NetworkStackConstants.IPV4_FLAG_MF
-import com.android.net.module.util.NetworkStackConstants.IPV4_FLAGS_OFFSET
 import com.android.net.module.util.NetworkStackConstants.IPV6_ADDR_ALL_NODES_MULTICAST
 import com.android.net.module.util.structs.PrefixInformationOption
 import com.android.networkstack.util.NetworkStackUtils
@@ -59,10 +59,6 @@
 import com.android.testutils.IPv4UdpFilter
 import com.android.testutils.TapPacketReader
 import com.android.testutils.UDP_HEADER_LENGTH
-import org.junit.After
-import org.junit.Assert.assertArrayEquals
-import org.junit.Before
-import org.junit.Test
 import java.io.FileDescriptor
 import java.net.Inet4Address
 import java.net.Inet6Address
@@ -71,8 +67,13 @@
 import kotlin.reflect.KClass
 import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
+import kotlin.test.assertNull
 import kotlin.test.assertTrue
 import kotlin.test.fail
+import org.junit.After
+import org.junit.Assert.assertArrayEquals
+import org.junit.Before
+import org.junit.Test
 
 class NetworkStackUtilsIntegrationTest {
     private val inst by lazy { InstrumentationRegistry.getInstrumentation() }
@@ -225,6 +226,41 @@
         assertSolicitedNodeMulticastAddress(addr3, TEST_INET6ADDR_3)
     }
 
+    @Test
+    fun testConvertMacAddressToEui64() {
+        // MAC address with universal/local bit set (the first byte: 0xBA)
+        var expected = byteArrayOf(
+                0xB8.toByte(), 0x98.toByte(), 0x76.toByte(), 0xFF.toByte(),
+                0xFE.toByte(), 0x54.toByte(), 0x32.toByte(), 0x10.toByte())
+        val srcEui64 = NetworkStackUtils.macAddressToEui64(TEST_SRC_MAC)
+        assertArrayEquals(expected, srcEui64)
+
+        // MAC address with universal/local bit unset (the first byte: 0x01).
+        expected = byteArrayOf(
+                0x03.toByte(), 0x23.toByte(), 0x45.toByte(), 0xFF.toByte(),
+                0xFE.toByte(), 0x67.toByte(), 0x89.toByte(), 0x0A.toByte())
+        val targetEui64 = NetworkStackUtils.macAddressToEui64(TEST_TARGET_MAC)
+        assertArrayEquals(expected, targetEui64)
+    }
+
+    @Test
+    fun testGenerateIpv6AddressFromEui64() {
+        val eui64 = NetworkStackUtils.macAddressToEui64(TEST_SRC_MAC)
+        var prefix = IpPrefix("2001:db8:1::/80")
+        // Don't accept the prefix length larger than 64.
+        assertNull(NetworkStackUtils.createInet6AddressFromEui64(prefix, eui64))
+
+        prefix = IpPrefix("2001:db8:1::/48")
+        // Don't accept the prefix length less than 64.
+        assertNull(NetworkStackUtils.createInet6AddressFromEui64(prefix, eui64))
+
+        prefix = IpPrefix("2001:db8:1::/64")
+        // IPv6 address string is formed by combining the IPv6 prefix("2001:db8:1::") and
+        // EUI64 converted from TEST_SRC_MAC, see above test for the output EUI64 example.
+        val expected = parseNumericAddress("2001:db8:1::b898:76ff:fe54:3210") as Inet6Address
+        assertEquals(expected, NetworkStackUtils.createInet6AddressFromEui64(prefix, eui64))
+    }
+
     private fun assertSocketReadErrno(msg: String, fd: FileDescriptor, errno: Int) {
         val received = ByteBuffer.allocate(TEST_MTU)
         try {
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index f9f7e64..f0747b1 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -16,6 +16,8 @@
 
 package android.net.apf;
 
+import static android.net.apf.ApfGenerator.Register.R0;
+import static android.net.apf.ApfGenerator.Register.R1;
 import static android.system.OsConstants.AF_UNIX;
 import static android.system.OsConstants.ARPHRD_ETHER;
 import static android.system.OsConstants.ETH_P_ARP;
@@ -51,7 +53,6 @@
 import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.apf.ApfFilter.ApfConfiguration;
 import android.net.apf.ApfGenerator.IllegalInstructionException;
-import android.net.apf.ApfGenerator.Register;
 import android.net.ip.IIpClientCallbacks;
 import android.net.ip.IpClient.IpClientCallbacksWrapper;
 import android.net.metrics.IpConnectivityLog;
@@ -155,7 +156,7 @@
     private static final byte SIZE8   = (byte)(1 << 1);
     private static final byte SIZE16  = (byte)(2 << 1);
     private static final byte SIZE32  = (byte)(3 << 1);
-    private static final byte R1 = 1;
+    private static final byte R1_REG = 1;
 
     private static ApfConfiguration getDefaultConfig() {
         ApfFilter.ApfConfiguration config = new ApfConfiguration();
@@ -176,16 +177,23 @@
         }
     }
 
+    private static void assertReturnCodesEqual(String msg, int expected, int got) {
+        assertEquals(msg, label(expected), label(got));
+    }
+
     private static void assertReturnCodesEqual(int expected, int got) {
         assertEquals(label(expected), label(got));
     }
 
     private void assertVerdict(int expected, byte[] program, byte[] packet, int filterAge) {
+        final String msg = "Unexpected APF verdict. To debug:\n"
+                + "  apf_run --program " + HexDump.toHexString(program)
+                + " --packet " +  HexDump.toHexString(packet) + " --trace | less\n  ";
         assertReturnCodesEqual(expected, apfSimulate(program, packet, null, filterAge));
     }
 
     private void assertVerdict(int expected, byte[] program, byte[] packet) {
-        assertReturnCodesEqual(expected, apfSimulate(program, packet, null, 0));
+        assertVerdict(expected, program, packet, 0);
     }
 
     private void assertPass(byte[] program, byte[] packet, int filterAge) {
@@ -293,7 +301,7 @@
         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
+        gen.addLoadImmediate(R0, 1);
         gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
         assertDrop(gen);
 
@@ -307,13 +315,13 @@
         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
+        gen.addLoadImmediate(R0, 1);
         gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test load immediate.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
@@ -337,35 +345,35 @@
 
         // Test and.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addAnd(123456789);
         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test left shift.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addLeftShift(1);
         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test right shift.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addRightShift(1);
         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test multiply.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 123456789);
+        gen.addLoadImmediate(R0, 123456789);
         gen.addMul(2);
         gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test divide.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addDiv(2);
         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
         assertDrop(gen);
@@ -378,61 +386,61 @@
 
         // Test add.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addLoadImmediate(R1, 1234567890);
         gen.addAddR1();
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test subtract.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, -1234567890);
+        gen.addLoadImmediate(R1, -1234567890);
         gen.addAddR1();
         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test or.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addLoadImmediate(R1, 1234567890);
         gen.addOrR1();
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test and.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addLoadImmediate(Register.R1, 123456789);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addLoadImmediate(R1, 123456789);
         gen.addAndR1();
         gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test left shift.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addLoadImmediate(R1, 1);
         gen.addLeftShiftR1();
         gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test right shift.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addLoadImmediate(Register.R1, -1);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addLoadImmediate(R1, -1);
         gen.addLeftShiftR1();
         gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test multiply.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 123456789);
-        gen.addLoadImmediate(Register.R1, 2);
+        gen.addLoadImmediate(R0, 123456789);
+        gen.addLoadImmediate(R1, 2);
         gen.addMulR1();
         gen.addJumpIfR0Equals(123456789 * 2, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test divide.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addLoadImmediate(Register.R1, 2);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addLoadImmediate(R1, 2);
         gen.addDivR1();
         gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
         assertDrop(gen);
@@ -445,53 +453,53 @@
 
         // Test byte load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoad8(Register.R0, 1);
+        gen.addLoad8(R0, 1);
         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test out of bounds load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoad8(Register.R0, 16);
+        gen.addLoad8(R0, 16);
         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test half-word load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoad16(Register.R0, 1);
+        gen.addLoad16(R0, 1);
         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test word load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoad32(Register.R0, 1);
+        gen.addLoad32(R0, 1);
         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test byte indexed load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1);
-        gen.addLoad8Indexed(Register.R0, 0);
+        gen.addLoadImmediate(R1, 1);
+        gen.addLoad8Indexed(R0, 0);
         gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test out of bounds indexed load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 8);
-        gen.addLoad8Indexed(Register.R0, 8);
+        gen.addLoadImmediate(R1, 8);
+        gen.addLoad8Indexed(R0, 8);
         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
         assertPass(gen, new byte[]{123,45,0,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test half-word indexed load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1);
-        gen.addLoad16Indexed(Register.R0, 0);
+        gen.addLoadImmediate(R1, 1);
+        gen.addLoad16Indexed(R0, 0);
         gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,67,0,0,0,0,0,0,0,0,0,0,0,0}, 0);
 
         // Test word indexed load.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1);
-        gen.addLoad32Indexed(Register.R0, 0);
+        gen.addLoadImmediate(R1, 1);
+        gen.addLoad32Indexed(R0, 0);
         gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{123,45,67,89,12,0,0,0,0,0,0,0,0,0,0}, 0);
 
@@ -500,7 +508,7 @@
         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
+        gen.addLoadImmediate(R0, 1);
         gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
         assertDrop(gen);
 
@@ -517,11 +525,11 @@
         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
+        gen.addLoadImmediate(R0, 1);
         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
         assertDrop(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 3);
+        gen.addLoadImmediate(R0, 3);
         gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
         assertDrop(gen);
 
@@ -530,8 +538,8 @@
         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 2);
-        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoadImmediate(R0, 2);
+        gen.addLoadImmediate(R1, 1);
         gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
         assertDrop(gen);
 
@@ -540,100 +548,100 @@
         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1);
+        gen.addLoadImmediate(R1, 1);
         gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test jumping if any bits set in register.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 3);
+        gen.addLoadImmediate(R1, 3);
         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
         assertPass(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 3);
-        gen.addLoadImmediate(Register.R0, 1);
+        gen.addLoadImmediate(R1, 3);
+        gen.addLoadImmediate(R0, 1);
         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
         assertDrop(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 3);
-        gen.addLoadImmediate(Register.R0, 3);
+        gen.addLoadImmediate(R1, 3);
+        gen.addLoadImmediate(R0, 3);
         gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test load from memory.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadFromMemory(Register.R0, 0);
+        gen.addLoadFromMemory(R0, 0);
         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test store to memory.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1234567890);
-        gen.addStoreToMemory(Register.R1, 12);
-        gen.addLoadFromMemory(Register.R0, 12);
+        gen.addLoadImmediate(R1, 1234567890);
+        gen.addStoreToMemory(R1, 12);
+        gen.addLoadFromMemory(R0, 12);
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test filter age pre-filled memory.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, gen.FILTER_AGE_MEMORY_SLOT);
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
 
         // Test packet size pre-filled memory.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, gen.PACKET_SIZE_MEMORY_SLOT);
         gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test IPv4 header size pre-filled memory.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
+        gen.addLoadFromMemory(R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
         gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
         assertDrop(gen, new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x45}, 0);
 
         // Test not.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addNot(Register.R0);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addNot(R0);
         gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test negate.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addNeg(Register.R0);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addNeg(R0);
         gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test move.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1234567890);
-        gen.addMove(Register.R0);
+        gen.addLoadImmediate(R1, 1234567890);
+        gen.addMove(R0);
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
-        gen.addMove(Register.R1);
+        gen.addLoadImmediate(R0, 1234567890);
+        gen.addMove(R1);
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test swap.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R1, 1234567890);
+        gen.addLoadImmediate(R1, 1234567890);
         gen.addSwap();
         gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
         assertDrop(gen);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1234567890);
+        gen.addLoadImmediate(R0, 1234567890);
         gen.addSwap();
         gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
         assertDrop(gen);
 
         // Test jump if bytes not equal.
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
-        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        gen.addLoadImmediate(R0, 1);
+        gen.addJumpIfBytesNotEqual(R0, new byte[]{123}, gen.DROP_LABEL);
         program = gen.generate();
         assertEquals(6, program.length);
         assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
@@ -644,21 +652,21 @@
         assertEquals(123, program[5]);
         assertDrop(program, new byte[MIN_PKT_SIZE], 0);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
-        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        gen.addLoadImmediate(R0, 1);
+        gen.addJumpIfBytesNotEqual(R0, new byte[]{123}, gen.DROP_LABEL);
         byte[] packet123 = {0,123,0,0,0,0,0,0,0,0,0,0,0,0,0};
         assertPass(gen, packet123, 0);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{123}, gen.DROP_LABEL);
+        gen.addJumpIfBytesNotEqual(R0, new byte[]{123}, gen.DROP_LABEL);
         assertDrop(gen, packet123, 0);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
-        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
+        gen.addLoadImmediate(R0, 1);
+        gen.addJumpIfBytesNotEqual(R0, new byte[]{1,2,30,4,5}, gen.DROP_LABEL);
         byte[] packet12345 = {0,1,2,3,4,5,0,0,0,0,0,0,0,0,0};
         assertDrop(gen, packet12345, 0);
         gen = new ApfGenerator(MIN_APF_VERSION);
-        gen.addLoadImmediate(Register.R0, 1);
-        gen.addJumpIfBytesNotEqual(Register.R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
+        gen.addLoadImmediate(R0, 1);
+        gen.addJumpIfBytesNotEqual(R0, new byte[]{1,2,3,4,5}, gen.DROP_LABEL);
         assertPass(gen, packet12345, 0);
     }
 
@@ -672,13 +680,13 @@
     public void testApfDataOpcodesWantApfV3() throws IllegalInstructionException, Exception {
         ApfGenerator gen = new ApfGenerator(MIN_APF_VERSION);
         try {
-            gen.addStoreData(Register.R0, 0);
+            gen.addStoreData(R0, 0);
             fail();
         } catch (IllegalInstructionException expected) {
             /* pass */
         }
         try {
-            gen.addLoadData(Register.R0, 0);
+            gen.addLoadData(R0, 0);
             fail();
         } catch (IllegalInstructionException expected) {
             /* pass */
@@ -694,22 +702,22 @@
 
         // 0-byte immediate: li R0, 0
         gen = new ApfGenerator(4);
-        gen.addLoadImmediate(Register.R0, 0);
+        gen.addLoadImmediate(R0, 0);
         assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate());
 
         // 1-byte immediate: li R0, 42
         gen = new ApfGenerator(4);
-        gen.addLoadImmediate(Register.R0, 42);
+        gen.addLoadImmediate(R0, 42);
         assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate());
 
         // 2-byte immediate: li R1, 0x1234
         gen = new ApfGenerator(4);
-        gen.addLoadImmediate(Register.R1, 0x1234);
-        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, 0x12, 0x34}, gen.generate());
+        gen.addLoadImmediate(R1, 0x1234);
+        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1_REG, 0x12, 0x34}, gen.generate());
 
         // 4-byte immediate: li R0, 0x12345678
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 0x12345678);
+        gen.addLoadImmediate(R0, 0x12345678);
         assertProgramEquals(
                 new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78},
                 gen.generate());
@@ -724,18 +732,18 @@
 
         // 1-byte negative immediate: li R0, -42
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, -42);
+        gen.addLoadImmediate(R0, -42);
         assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate());
 
         // 2-byte negative immediate: li R1, -0x1122
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R1, -0x1122);
-        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
+        gen.addLoadImmediate(R1, -0x1122);
+        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1_REG, (byte)0xEE, (byte)0xDE},
                 gen.generate());
 
         // 4-byte negative immediate: li R0, -0x11223344
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, -0x11223344);
+        gen.addLoadImmediate(R0, -0x11223344);
         assertProgramEquals(
                 new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
                 gen.generate());
@@ -750,25 +758,26 @@
 
         // Load data with no offset: lddw R0, [0 + r1]
         gen = new ApfGenerator(3);
-        gen.addLoadData(Register.R0, 0);
+        gen.addLoadData(R0, 0);
         assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate());
 
         // Store data with 8bit negative offset: lddw r0, [-42 + r1]
         gen = new ApfGenerator(3);
-        gen.addStoreData(Register.R0, -42);
+        gen.addStoreData(R0, -42);
         assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate());
 
         // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0]
         gen = new ApfGenerator(3);
-        gen.addStoreData(Register.R1, -0x1122);
-        assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
+        gen.addStoreData(R1, -0x1122);
+        assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1_REG, (byte)0xEE, (byte)0xDE},
                 gen.generate());
 
         // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0]
         gen = new ApfGenerator(3);
-        gen.addLoadData(Register.R1, 0xDEADBEEF);
+        gen.addLoadData(R1, 0xDEADBEEF);
         assertProgramEquals(
-                new byte[]{LDDW_OP | SIZE32 | R1, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
+                new byte[]{LDDW_OP | SIZE32 | R1_REG,
+                        (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
                 gen.generate());
     }
 
@@ -788,9 +797,9 @@
         // Expect value 0x87654321 to be stored starting from address -11 from the end of the
         // data buffer, in big-endian order.
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 0x87654321);
-        gen.addLoadImmediate(Register.R1, -5);
-        gen.addStoreData(Register.R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
+        gen.addLoadImmediate(R0, 0x87654321);
+        gen.addLoadImmediate(R1, -5);
+        gen.addStoreData(R0, -6);  // -5 + -6 = -11 (offset +5 with data_len=16)
         expected_data[5] = (byte)0x87;
         expected_data[6] = (byte)0x65;
         expected_data[7] = (byte)0x43;
@@ -805,8 +814,8 @@
     public void testApfDataRead() throws IllegalInstructionException, Exception {
         // Program that DROPs if address 10 (-6) contains 0x87654321.
         ApfGenerator gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R1, 1000);
-        gen.addLoadData(Register.R0, -1006);  // 1000 + -1006 = -6 (offset +10 with data_len=16)
+        gen.addLoadImmediate(R1, 1000);
+        gen.addLoadData(R0, -1006);  // 1000 + -1006 = -6 (offset +10 with data_len=16)
         gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
         byte[] program = gen.generate();
         byte[] packet = new byte[MIN_PKT_SIZE];
@@ -834,10 +843,10 @@
     @Test
     public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
         ApfGenerator gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R1, -22);
-        gen.addLoadData(Register.R0, 0);  // Load from address 32 -22 + 0 = 10
+        gen.addLoadImmediate(R1, -22);
+        gen.addLoadData(R0, 0);  // Load from address 32 -22 + 0 = 10
         gen.addAdd(0x78453412);  // 87654321 + 78453412 = FFAA7733
-        gen.addStoreData(Register.R0, 4);  // Write back to address 32 -22 + 4 = 14
+        gen.addStoreData(R0, 4);  // Write back to address 32 -22 + 4 = 14
 
         byte[] packet = new byte[MIN_PKT_SIZE];
         byte[] data = new byte[32];
@@ -861,36 +870,36 @@
 
         // Program that DROPs unconditionally. This is our the baseline.
         ApfGenerator gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 3);
-        gen.addLoadData(Register.R1, 7);
+        gen.addLoadImmediate(R0, 3);
+        gen.addLoadData(R1, 7);
         gen.addJump(gen.DROP_LABEL);
         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
 
         // Same program as before, but this time we're trying to load past the end of the data.
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 20);
-        gen.addLoadData(Register.R1, 15);  // 20 + 15 > 32
+        gen.addLoadImmediate(R0, 20);
+        gen.addLoadData(R1, 15);  // 20 + 15 > 32
         gen.addJump(gen.DROP_LABEL);  // Not reached.
         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
 
         // Subtracting an immediate should work...
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 20);
-        gen.addLoadData(Register.R1, -4);
+        gen.addLoadImmediate(R0, 20);
+        gen.addLoadData(R1, -4);
         gen.addJump(gen.DROP_LABEL);
         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
 
         // ...and underflowing simply wraps around to the end of the buffer...
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 20);
-        gen.addLoadData(Register.R1, -30);
+        gen.addLoadImmediate(R0, 20);
+        gen.addLoadData(R1, -30);
         gen.addJump(gen.DROP_LABEL);
         assertDataMemoryContents(DROP, gen.generate(), packet, data, expected_data);
 
         // ...but doesn't allow accesses before the start of the buffer
         gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R0, 20);
-        gen.addLoadData(Register.R1, -1000);
+        gen.addLoadImmediate(R0, 20);
+        gen.addLoadData(R1, -1000);
         gen.addJump(gen.DROP_LABEL);  // Not reached.
         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
     }