Merge "[DU02]Remove DevicePolicyManagerInternal from NetworkStatsAccess"
diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp
index 9c07f39..0bda923 100644
--- a/framework-t/Sources.bp
+++ b/framework-t/Sources.bp
@@ -100,15 +100,58 @@
     ],
 }
 
+// IpSec related libraries.
+
+filegroup {
+    name: "framework-connectivity-ipsec-sources",
+    srcs: [
+        "src/android/net/IIpSecService.aidl",
+        "src/android/net/IpSec*.*",
+    ],
+    path: "src",
+    visibility: [
+        "//visibility:private",
+    ],
+}
+
+// Ethernet related libraries.
+
+filegroup {
+    name: "framework-connectivity-ethernet-sources",
+    srcs: [
+        "src/android/net/EthernetManager.java",
+        "src/android/net/EthernetNetworkSpecifier.java",
+        "src/android/net/IEthernetManager.aidl",
+        "src/android/net/IEthernetServiceListener.aidl",
+        "src/android/net/ITetheredInterfaceCallback.aidl",
+    ],
+    path: "src",
+    visibility: [
+        "//visibility:private",
+    ],
+}
+
 // Connectivity-T common libraries.
 
 filegroup {
+    name: "framework-connectivity-tiramisu-internal-sources",
+    srcs: [
+        "src/android/net/ConnectivityFrameworkInitializerTiramisu.java",
+    ],
+    path: "src",
+    visibility: [
+        "//visibility:private",
+    ],
+}
+
+filegroup {
     name: "framework-connectivity-tiramisu-sources",
     srcs: [
+        ":framework-connectivity-ethernet-sources",
+        ":framework-connectivity-ipsec-sources",
         ":framework-connectivity-netstats-sources",
         ":framework-connectivity-nsd-sources",
+        ":framework-connectivity-tiramisu-internal-sources",
     ],
-    visibility: [
-        "//frameworks/base",
-    ],
-}
\ No newline at end of file
+    visibility: ["//frameworks/base"],
+}
diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java
index 8a6c85d..ca83309 100644
--- a/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -45,8 +45,6 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.DataUnit;
@@ -135,15 +133,6 @@
 
     private int mFlags;
 
-    /**
-     * {@hide}
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public NetworkStatsManager(Context context) throws ServiceNotFoundException {
-        this(context, INetworkStatsService.Stub.asInterface(
-                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
-    }
-
     /** @hide */
     @VisibleForTesting
     public NetworkStatsManager(Context context, INetworkStatsService service) {
diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
new file mode 100644
index 0000000..630f902
--- /dev/null
+++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.SystemApi;
+import android.app.SystemServiceRegistry;
+import android.content.Context;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
+
+/**
+ * Class for performing registration for Connectivity services which are exposed via updatable APIs
+ * since Android T.
+ *
+ * @hide
+ */
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+public final class ConnectivityFrameworkInitializerTiramisu {
+    private ConnectivityFrameworkInitializerTiramisu() {}
+
+    /**
+     * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to
+     * {@link Context}, so that {@link Context#getSystemService} can return them.
+     *
+     * @throws IllegalStateException if this is called anywhere besides
+     * {@link SystemServiceRegistry}.
+     */
+    public static void registerServiceWrappers() {
+        SystemServiceRegistry.registerContextAwareService(
+                Context.NSD_SERVICE,
+                NsdManager.class,
+                (context, serviceBinder) -> {
+                    INsdManager service = INsdManager.Stub.asInterface(serviceBinder);
+                    return new NsdManager(context, service);
+                }
+        );
+    }
+}
diff --git a/core/java/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java
similarity index 100%
rename from core/java/android/net/EthernetManager.java
rename to framework-t/src/android/net/EthernetManager.java
diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java
similarity index 100%
rename from core/java/android/net/EthernetNetworkSpecifier.java
rename to framework-t/src/android/net/EthernetNetworkSpecifier.java
diff --git a/core/java/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl
similarity index 100%
rename from core/java/android/net/IEthernetManager.aidl
rename to framework-t/src/android/net/IEthernetManager.aidl
diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/framework-t/src/android/net/IEthernetServiceListener.aidl
similarity index 100%
rename from core/java/android/net/IEthernetServiceListener.aidl
rename to framework-t/src/android/net/IEthernetServiceListener.aidl
diff --git a/core/java/android/net/IIpSecService.aidl b/framework-t/src/android/net/IIpSecService.aidl
similarity index 100%
rename from core/java/android/net/IIpSecService.aidl
rename to framework-t/src/android/net/IIpSecService.aidl
diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
similarity index 100%
rename from core/java/android/net/ITetheredInterfaceCallback.aidl
rename to framework-t/src/android/net/ITetheredInterfaceCallback.aidl
diff --git a/core/java/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java
similarity index 97%
rename from core/java/android/net/IpSecAlgorithm.java
rename to framework-t/src/android/net/IpSecAlgorithm.java
index 8605248..a84e7a9 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/framework-t/src/android/net/IpSecAlgorithm.java
@@ -23,7 +23,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.HexDump;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -297,7 +296,7 @@
         return mTruncLenBits;
     }
 
-    /* Parcelable Implementation */
+    /** Parcelable Implementation */
     public int describeContents() {
         return 0;
     }
@@ -469,20 +468,12 @@
         }
     }
 
-    // Because encryption keys are sensitive and userdebug builds are used by large user pools
-    // such as beta testers, we only allow sensitive info such as keys on eng builds.
-    private static boolean isUnsafeBuild() {
-        return Build.IS_DEBUGGABLE && Build.IS_ENG;
-    }
-
     @Override
     @NonNull
     public String toString() {
         return new StringBuilder()
                 .append("{mName=")
                 .append(mName)
-                .append(", mKey=")
-                .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "<hidden>")
                 .append(", mTruncLenBits=")
                 .append(mTruncLenBits)
                 .append("}")
diff --git a/core/java/android/net/IpSecConfig.aidl b/framework-t/src/android/net/IpSecConfig.aidl
similarity index 100%
rename from core/java/android/net/IpSecConfig.aidl
rename to framework-t/src/android/net/IpSecConfig.aidl
diff --git a/core/java/android/net/IpSecConfig.java b/framework-t/src/android/net/IpSecConfig.java
similarity index 100%
rename from core/java/android/net/IpSecConfig.java
rename to framework-t/src/android/net/IpSecConfig.java
diff --git a/core/java/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
similarity index 98%
rename from core/java/android/net/IpSecManager.java
rename to framework-t/src/android/net/IpSecManager.java
index c106807..0d15dff 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -17,8 +17,6 @@
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -46,6 +44,7 @@
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.Socket;
+import java.util.Objects;
 
 /**
  * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
@@ -86,6 +85,7 @@
      *
      * @hide
      */
+    @SystemApi(client = MODULE_LIBRARIES)
     public static final int DIRECTION_FWD = 2;
 
     /**
@@ -99,9 +99,9 @@
 
     /** @hide */
     public interface Status {
-        public static final int OK = 0;
-        public static final int RESOURCE_UNAVAILABLE = 1;
-        public static final int SPI_UNAVAILABLE = 2;
+        int OK = 0;
+        int RESOURCE_UNAVAILABLE = 1;
+        int SPI_UNAVAILABLE = 2;
     }
 
     /** @hide */
@@ -276,7 +276,7 @@
      * @param destinationAddress the destination address for traffic bearing the requested SPI.
      *     For inbound traffic, the destination should be an address currently assigned on-device.
      * @return the reserved SecurityParameterIndex
-     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+     * @throws ResourceUnavailableException indicating that too many SPIs are
      *     currently allocated for this user
      */
     @NonNull
@@ -307,9 +307,9 @@
      * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See
      *     RFC 4303 Section 2.1.
      * @return the reserved SecurityParameterIndex
-     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
+     * @throws ResourceUnavailableException indicating that too many SPIs are
      *     currently allocated for this user
-     * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
+     * @throws SpiUnavailableException indicating that the requested SPI could not be
      *     reserved
      */
     @NonNull
@@ -988,7 +988,7 @@
      */
     public IpSecManager(Context ctx, IIpSecService service) {
         mContext = ctx;
-        mService = checkNotNull(service, "missing service");
+        mService = Objects.requireNonNull(service, "missing service");
     }
 
     private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
diff --git a/core/java/android/net/IpSecSpiResponse.aidl b/framework-t/src/android/net/IpSecSpiResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecSpiResponse.aidl
rename to framework-t/src/android/net/IpSecSpiResponse.aidl
diff --git a/core/java/android/net/IpSecSpiResponse.java b/framework-t/src/android/net/IpSecSpiResponse.java
similarity index 100%
rename from core/java/android/net/IpSecSpiResponse.java
rename to framework-t/src/android/net/IpSecSpiResponse.java
diff --git a/core/java/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java
similarity index 96%
rename from core/java/android/net/IpSecTransform.java
rename to framework-t/src/android/net/IpSecTransform.java
index b48c1fd..36199a0 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/framework-t/src/android/net/IpSecTransform.java
@@ -33,7 +33,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
 
 import dalvik.system.CloseGuard;
 
@@ -41,6 +40,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.InetAddress;
+import java.util.Objects;
 
 /**
  * This class represents a transform, which roughly corresponds to an IPsec Security Association.
@@ -255,7 +255,7 @@
         @NonNull
         public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setEncryption(algo);
             return this;
         }
@@ -270,7 +270,7 @@
         @NonNull
         public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
             // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setAuthentication(algo);
             return this;
         }
@@ -290,7 +290,7 @@
          */
         @NonNull
         public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
-            Preconditions.checkNotNull(algo);
+            Objects.requireNonNull(algo);
             mConfig.setAuthenticatedEncryption(algo);
             return this;
         }
@@ -311,7 +311,7 @@
         @NonNull
         public IpSecTransform.Builder setIpv4Encapsulation(
                 @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
-            Preconditions.checkNotNull(localSocket);
+            Objects.requireNonNull(localSocket);
             mConfig.setEncapType(ENCAP_ESPINUDP);
             if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
@@ -348,8 +348,8 @@
                 @NonNull IpSecManager.SecurityParameterIndex spi)
                 throws IpSecManager.ResourceUnavailableException,
                         IpSecManager.SpiUnavailableException, IOException {
-            Preconditions.checkNotNull(sourceAddress);
-            Preconditions.checkNotNull(spi);
+            Objects.requireNonNull(sourceAddress);
+            Objects.requireNonNull(spi);
             if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
@@ -387,8 +387,8 @@
                 @NonNull IpSecManager.SecurityParameterIndex spi)
                 throws IpSecManager.ResourceUnavailableException,
                         IpSecManager.SpiUnavailableException, IOException {
-            Preconditions.checkNotNull(sourceAddress);
-            Preconditions.checkNotNull(spi);
+            Objects.requireNonNull(sourceAddress);
+            Objects.requireNonNull(spi);
             if (spi.getResourceId() == INVALID_RESOURCE_ID) {
                 throw new IllegalArgumentException("Invalid SecurityParameterIndex");
             }
@@ -404,7 +404,7 @@
          * @param context current context
          */
         public Builder(@NonNull Context context) {
-            Preconditions.checkNotNull(context);
+            Objects.requireNonNull(context);
             mContext = context;
             mConfig = new IpSecConfig();
         }
diff --git a/core/java/android/net/IpSecTransformResponse.aidl b/framework-t/src/android/net/IpSecTransformResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecTransformResponse.aidl
rename to framework-t/src/android/net/IpSecTransformResponse.aidl
diff --git a/core/java/android/net/IpSecTransformResponse.java b/framework-t/src/android/net/IpSecTransformResponse.java
similarity index 95%
rename from core/java/android/net/IpSecTransformResponse.java
rename to framework-t/src/android/net/IpSecTransformResponse.java
index a384889..363f316 100644
--- a/core/java/android/net/IpSecTransformResponse.java
+++ b/framework-t/src/android/net/IpSecTransformResponse.java
@@ -60,7 +60,8 @@
         resourceId = in.readInt();
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecTransformResponse> CREATOR =
+    @android.annotation.NonNull
+    public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
             new Parcelable.Creator<IpSecTransformResponse>() {
                 public IpSecTransformResponse createFromParcel(Parcel in) {
                     return new IpSecTransformResponse(in);
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecTunnelInterfaceResponse.aidl
rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
similarity index 95%
rename from core/java/android/net/IpSecTunnelInterfaceResponse.java
rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
index e3411e0..127e30a 100644
--- a/core/java/android/net/IpSecTunnelInterfaceResponse.java
+++ b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
@@ -65,7 +65,8 @@
         interfaceName = in.readString();
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
+    @android.annotation.NonNull
+    public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
             new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
                 public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
                     return new IpSecTunnelInterfaceResponse(in);
diff --git a/core/java/android/net/IpSecUdpEncapResponse.aidl b/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
similarity index 100%
rename from core/java/android/net/IpSecUdpEncapResponse.aidl
rename to framework-t/src/android/net/IpSecUdpEncapResponse.aidl
diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/framework-t/src/android/net/IpSecUdpEncapResponse.java
similarity index 96%
rename from core/java/android/net/IpSecUdpEncapResponse.java
rename to framework-t/src/android/net/IpSecUdpEncapResponse.java
index 4e7ba9b..732cf19 100644
--- a/core/java/android/net/IpSecUdpEncapResponse.java
+++ b/framework-t/src/android/net/IpSecUdpEncapResponse.java
@@ -18,6 +18,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 
@@ -83,7 +84,8 @@
         fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
     }
 
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
+    @android.annotation.NonNull
+    public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
             new Parcelable.Creator<IpSecUdpEncapResponse>() {
                 public IpSecUdpEncapResponse createFromParcel(Parcel in) {
                     return new IpSecUdpEncapResponse(in);
diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java
index c7ffc19..1986b83 100644
--- a/framework-t/src/android/net/NetworkStats.java
+++ b/framework-t/src/android/net/NetworkStats.java
@@ -16,7 +16,7 @@
 
 package android.net;
 
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java
index 0d3b9ed..8d1347e 100644
--- a/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/framework-t/src/android/net/NetworkStatsCollection.java
@@ -30,7 +30,7 @@
 import static android.net.TrafficStats.UID_REMOVED;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
 
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
 import android.os.Binder;
 import android.service.NetworkStatsCollectionKeyProto;
diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java
index a875e1a..3eef4ee 100644
--- a/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/framework-t/src/android/net/NetworkStatsHistory.java
@@ -28,8 +28,8 @@
 import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
-import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
 import static com.android.internal.util.ArrayUtils.total;
+import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java
index 8b9c14d..d852913 100644
--- a/framework-t/src/android/net/NetworkTemplate.java
+++ b/framework-t/src/android/net/NetworkTemplate.java
@@ -24,6 +24,8 @@
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
 import static android.net.NetworkIdentity.OEM_NONE;
+import static android.net.NetworkIdentity.OEM_PAID;
+import static android.net.NetworkIdentity.OEM_PRIVATE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
@@ -35,6 +37,7 @@
 import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.wifi.WifiInfo.sanitizeSsid;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -44,15 +47,21 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArraySet;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 /**
  * Predicate used to match {@link NetworkIdentity}, usually when collecting
@@ -60,40 +69,88 @@
  *
  * @hide
  */
-public class NetworkTemplate implements Parcelable {
-    private static final String TAG = "NetworkTemplate";
+// @SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkTemplate implements Parcelable {
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "MATCH_" }, value = {
+            MATCH_MOBILE,
+            MATCH_WIFI,
+            MATCH_ETHERNET,
+            MATCH_BLUETOOTH,
+            MATCH_CARRIER
+    })
+    public @interface TemplateMatchRule{}
 
+    /** Match rule to match cellular networks with given Subscriber Ids. */
     public static final int MATCH_MOBILE = 1;
+    /** Match rule to match wifi networks. */
     public static final int MATCH_WIFI = 4;
+    /** Match rule to match ethernet networks. */
     public static final int MATCH_ETHERNET = 5;
+    /**
+     * Match rule to match all cellular networks.
+     *
+     * @hide
+     */
     public static final int MATCH_MOBILE_WILDCARD = 6;
+    /**
+     * Match rule to match all wifi networks.
+     *
+     * @hide
+     */
     public static final int MATCH_WIFI_WILDCARD = 7;
+    /** Match rule to match bluetooth networks. */
     public static final int MATCH_BLUETOOTH = 8;
+    /**
+     * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type.
+     *
+     * @hide
+     */
     public static final int MATCH_PROXY = 9;
+    /**
+     * Match rule to match all networks with subscriberId inside the template. Some carriers
+     * may offer non-cellular networks like WiFi, which will be matched by this rule.
+     */
     public static final int MATCH_CARRIER = 10;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "SUBSCRIBER_ID_MATCH_RULE_" }, value = {
+            SUBSCRIBER_ID_MATCH_RULE_EXACT,
+            SUBSCRIBER_ID_MATCH_RULE_ALL
+    })
+    public @interface SubscriberIdMatchRule{}
     /**
      * Value of the match rule of the subscriberId to match networks with specific subscriberId.
+     *
+     * @hide
      */
     public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0;
     /**
      * Value of the match rule of the subscriberId to match networks with any subscriberId which
      * includes null and non-null.
+     *
+     * @hide
      */
     public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1;
 
-    /**
-     * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that
-     * should be fixed), so it's not possible to want to match null vs
-     * non-null. Therefore it's fine to use null as a sentinel for Network ID.
-     */
+    // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL.
+    /** @hide */
     public static final String WIFI_NETWORKID_ALL = null;
 
     /**
+     * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that
+     * should be fixed), so it's not possible to want to match null vs
+     * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key.
+     *
+     * @hide
+     */
+    public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL;
+
+    /**
      * Include all network types when filtering. This is meant to merge in with the
      * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
-     *
-     * @hide
      */
     public static final int NETWORK_TYPE_ALL = -1;
     /**
@@ -106,21 +163,37 @@
      */
     public static final int NETWORK_TYPE_5G_NSA = -2;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "OEM_MANAGED_" }, value = {
+            OEM_MANAGED_ALL,
+            OEM_MANAGED_NO,
+            OEM_MANAGED_YES,
+            OEM_MANAGED_PAID,
+            OEM_MANAGED_PRIVATE
+    })
+    public @interface OemManaged{}
+
     /**
      * Value to match both OEM managed and unmanaged networks (all networks).
-     * @hide
      */
     public static final int OEM_MANAGED_ALL = -1;
     /**
      * Value to match networks which are not OEM managed.
-     * @hide
      */
     public static final int OEM_MANAGED_NO = OEM_NONE;
     /**
      * Value to match any OEM managed network.
-     * @hide
      */
     public static final int OEM_MANAGED_YES = -2;
+    /**
+     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
+     */
+    public static final int OEM_MANAGED_PAID = OEM_PAID;
+    /**
+     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
+     */
+    public static final int OEM_MANAGED_PRIVATE = OEM_PRIVATE;
 
     private static boolean isKnownMatchRule(final int rule) {
         switch (rule) {
@@ -142,6 +215,8 @@
     /**
      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
      * the given IMSI.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
@@ -152,6 +227,8 @@
      * Template to match cellular networks with the given IMSI, {@code ratType} and
      * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
      * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
             @NetworkType int ratType, int metered) {
@@ -168,6 +245,8 @@
     /**
      * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
      * regardless of IMSI.
+     *
+     * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static NetworkTemplate buildTemplateMobileWildcard() {
@@ -177,6 +256,8 @@
     /**
      * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
      * regardless of SSID.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateWifiWildcard() {
@@ -185,6 +266,7 @@
         return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
     }
 
+    /** @hide */
     @Deprecated
     @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateWifi() {
@@ -194,6 +276,8 @@
     /**
      * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
      * given SSID.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) {
         Objects.requireNonNull(networkId);
@@ -208,7 +292,10 @@
      * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID,
      * and IMSI.
      *
-     * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID.
+     * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless
+     * of SSID.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateWifi(@Nullable String networkId,
             @Nullable String subscriberId) {
@@ -221,6 +308,8 @@
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
      * networks together.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public static NetworkTemplate buildTemplateEthernet() {
@@ -230,6 +319,8 @@
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
      * networks together.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateBluetooth() {
         return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
@@ -238,6 +329,8 @@
     /**
      * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
      * networks together.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateProxy() {
         return new NetworkTemplate(MATCH_PROXY, null, null);
@@ -245,6 +338,8 @@
 
     /**
      * Template to match all metered carrier networks with the given IMSI.
+     *
+     * @hide
      */
     public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
         Objects.requireNonNull(subscriberId);
@@ -267,6 +362,7 @@
      */
     private final String[] mMatchSubscriberIds;
 
+    // TODO: Change variable name to match the Api surface.
     private final String mNetworkId;
 
     // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
@@ -283,14 +379,14 @@
     // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
     private final int mOemManaged;
 
-    private void checkValidSubscriberIdMatchRule() {
-        switch (mMatchRule) {
+    private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) {
+        switch (matchRule) {
             case MATCH_MOBILE:
             case MATCH_CARRIER:
                 // MOBILE and CARRIER templates must always specify a subscriber ID.
-                if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
-                    throw new IllegalArgumentException("Invalid SubscriberIdMatchRule"
-                            + "on match rule: " + getMatchRuleName(mMatchRule));
+                if (subscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
+                    throw new IllegalArgumentException("Invalid SubscriberIdMatchRule "
+                            + "on match rule: " + getMatchRuleName(matchRule));
                 }
                 return;
             default:
@@ -298,12 +394,14 @@
         }
     }
 
+    /** @hide */
     // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
     @UnsupportedAppUsage
     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
         this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
     }
 
+    /** @hide */
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId) {
         // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
@@ -316,6 +414,7 @@
                 OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
+    /** @hide */
     // TODO: Remove it after updating all of the caller.
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId, int metered, int roaming, int defaultNetwork, int subType,
@@ -324,6 +423,7 @@
                 defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
+    /** @hide */
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId, int metered, int roaming, int defaultNetwork, int subType,
             int oemManaged, int subscriberIdMatchRule) {
@@ -339,7 +439,7 @@
         mSubType = subType;
         mOemManaged = oemManaged;
         mSubscriberIdMatchRule = subscriberIdMatchRule;
-        checkValidSubscriberIdMatchRule();
+        checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
         if (!isKnownMatchRule(matchRule)) {
             throw new IllegalArgumentException("Unknown network template rule " + matchRule
                     + " will not match any identity.");
@@ -360,7 +460,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mMatchRule);
         dest.writeString(mSubscriberId);
         dest.writeStringArray(mMatchSubscriberIds);
@@ -437,7 +537,7 @@
         return false;
     }
 
-    private String subscriberIdMatchRuleToString(int rule) {
+    private static String subscriberIdMatchRuleToString(int rule) {
         switch (rule) {
             case SUBSCRIBER_ID_MATCH_RULE_EXACT:
                 return "EXACT_MATCH";
@@ -448,6 +548,7 @@
         }
     }
 
+    /** @hide */
     public boolean isMatchRuleMobile() {
         switch (mMatchRule) {
             case MATCH_MOBILE:
@@ -458,48 +559,108 @@
         }
     }
 
-    public boolean isPersistable() {
+    /**
+     * Get match rule of the template. See {@code MATCH_*}.
+     */
+    @UnsupportedAppUsage
+    public int getMatchRule() {
+        // Wildcard rules are not exposed. For external callers, convert wildcard rules to
+        // exposed rules before returning.
         switch (mMatchRule) {
             case MATCH_MOBILE_WILDCARD:
+                return MATCH_MOBILE;
             case MATCH_WIFI_WILDCARD:
-                return false;
-            case MATCH_CARRIER:
-                return mSubscriberId != null;
-            case MATCH_WIFI:
-                if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
-                        && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
-                    return false;
-                }
-                return true;
+                return MATCH_WIFI;
             default:
-                return true;
+                return mMatchRule;
         }
     }
 
-    @UnsupportedAppUsage
-    public int getMatchRule() {
-        return mMatchRule;
-    }
-
+    /**
+     * Get subscriber Id of the template.
+     */
+    @Nullable
     @UnsupportedAppUsage
     public String getSubscriberId() {
         return mSubscriberId;
     }
 
+    /**
+     * Get set of subscriber Ids of the template.
+     */
+    @NonNull
+    public Set<String> getSubscriberIds() {
+        return new ArraySet<>(Arrays.asList(mMatchSubscriberIds));
+    }
+
+    /**
+     * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}.
+     */
+    @Nullable
+    public String getWifiNetworkKey() {
+        return mNetworkId;
+    }
+
+    /** @hide */
+    // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}.
+    @Nullable
     public String getNetworkId() {
         return mNetworkId;
     }
 
+    /**
+     * Get Subscriber Id Match Rule of the template.
+     *
+     * @hide
+     */
     public int getSubscriberIdMatchRule() {
         return mSubscriberIdMatchRule;
     }
 
+    /**
+     * Get meteredness filter of the template.
+     */
+    @NetworkStats.Meteredness
     public int getMeteredness() {
         return mMetered;
     }
 
     /**
+     * Get roaming filter of the template.
+     */
+    @NetworkStats.Roaming
+    public int getRoaming() {
+        return mRoaming;
+    }
+
+    /**
+     * Get the default network status filter of the template.
+     */
+    @NetworkStats.DefaultNetwork
+    public int getDefaultNetworkStatus() {
+        return mDefaultNetwork;
+    }
+
+    /**
+     * Get the Radio Access Technology(RAT) type filter of the template.
+     */
+    public int getRatType() {
+        return mSubType;
+    }
+
+    /**
+     * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or
+     * {@code android.net.NetworkIdentity#OEM_*}.
+     */
+    @OemManaged
+    public int getOemManaged() {
+        return mOemManaged;
+    }
+
+    /**
      * Test if given {@link NetworkIdentity} matches this template.
+     *
+     * @hide
      */
     public boolean matches(NetworkIdentity ident) {
         if (!matchesMetered(ident)) return false;
@@ -565,6 +726,8 @@
      * Check if this template matches {@code subscriberId}. Returns true if this
      * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
      * {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
+     *
+     * @hide
      */
     public boolean matchesSubscriberId(@Nullable String subscriberId) {
         return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL
@@ -573,10 +736,10 @@
 
     /**
      * Check if network with matching SSID. Returns true when the SSID matches, or when
-     * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}.
+     * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}.
      */
     private boolean matchesWifiNetworkId(@Nullable String networkId) {
-        return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
+        return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL)
                 || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId));
     }
 
@@ -599,10 +762,13 @@
      * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
      *
      * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+     *
+     * @hide
      */
     // TODO: 1. Consider move this to TelephonyManager if used by other modules.
     //       2. Consider make this configurable.
     //       3. Use TelephonyManager APIs when available.
+    // TODO: @SystemApi when ready.
     public static int getCollapsedRatType(int ratType) {
         switch (ratType) {
             case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -639,7 +805,10 @@
     /**
      * Return all supported collapsed RAT types that could be returned by
      * {@link #getCollapsedRatType(int)}.
+     *
+     * @hide
      */
+    // TODO: @SystemApi when ready.
     @NonNull
     public static final int[] getAllCollapsedRatTypes() {
         final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
@@ -779,6 +948,8 @@
      * active merge set [A,B], we'd return a new template that primarily matches
      * A, but also matches B.
      * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
+     *
+     * @hide
      */
     @UnsupportedAppUsage
     public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
@@ -797,7 +968,10 @@
      * For example, given an incoming template matching B, and the currently
      * active merge set [A,B], we'd return a new template that primarily matches
      * A, but also matches B.
+     *
+     * @hide
      */
+    // TODO: @SystemApi when ready.
     public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
         // Now there are several types of network which uses SubscriberId to store network
         // information. For instances:
@@ -830,4 +1004,184 @@
             return new NetworkTemplate[size];
         }
     };
+
+    /**
+     * Builder class for NetworkTemplate.
+     */
+    public static final class Builder {
+        private final int mMatchRule;
+        // Use a SortedSet to provide a deterministic order when fetching the first one.
+        @NonNull
+        private final SortedSet<String> mMatchSubscriberIds = new TreeSet<>();
+        @Nullable
+        private String mWifiNetworkKey;
+
+        // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
+        private int mMetered;
+        private int mRoaming;
+        private int mDefaultNetwork;
+        private int mRatType;
+
+        // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}.
+        private int mOemManaged;
+
+        /**
+         * Creates a new Builder with given match rule to construct NetworkTemplate objects.
+         *
+         * @param matchRule the match rule of the template, see {@code MATCH_*}.
+         */
+        public Builder(@TemplateMatchRule final int matchRule) {
+            assertRequestableMatchRule(matchRule);
+            // Initialize members with default values.
+            mMatchRule = matchRule;
+            mWifiNetworkKey = WIFI_NETWORK_KEY_ALL;
+            mMetered = METERED_ALL;
+            mRoaming = ROAMING_ALL;
+            mDefaultNetwork = DEFAULT_NETWORK_ALL;
+            mRatType = NETWORK_TYPE_ALL;
+            mOemManaged = OEM_MANAGED_ALL;
+        }
+
+        /**
+         * Set the Subscriber Ids. Calling this function with an empty set represents
+         * the intention of matching any Subscriber Ids.
+         *
+         * @param subscriberIds the list of Subscriber Ids.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setSubscriberIds(@NonNull Set<String> subscriberIds) {
+            Objects.requireNonNull(subscriberIds);
+            mMatchSubscriberIds.clear();
+            mMatchSubscriberIds.addAll(subscriberIds);
+            return this;
+        }
+
+        /**
+         * Set the Wifi Network Key.
+         *
+         * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}.
+         *                       Or null to match all networks.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
+            mWifiNetworkKey = wifiNetworkKey;
+            return this;
+        }
+
+        /**
+         * Set the meteredness filter.
+         *
+         * @param metered the meteredness filter.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setMeteredness(@NetworkStats.Meteredness int metered) {
+            mMetered = metered;
+            return this;
+        }
+
+        /**
+         * Set the roaming filter.
+         *
+         * @param roaming the roaming filter.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setRoaming(@NetworkStats.Roaming int roaming) {
+            mRoaming = roaming;
+            return this;
+        }
+
+        /**
+         * Set the default network status filter.
+         *
+         * @param defaultNetwork the default network status filter.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) {
+            mDefaultNetwork = defaultNetwork;
+            return this;
+        }
+
+        /**
+         * Set the Radio Access Technology(RAT) type filter.
+         *
+         * @param ratType the Radio Access Technology(RAT) type filter. Use
+         *                {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
+         *                See {@code TelephonyManager.NETWORK_TYPE_*}.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setRatType(@NetworkType int ratType) {
+            // Input will be validated with the match rule when building the template.
+            mRatType = ratType;
+            return this;
+        }
+
+        /**
+         * Set the OEM managed filter.
+         *
+         * @param oemManaged the match rule to match different type of OEM managed network or
+         *                   unmanaged networks. See {@code OEM_MANAGED_*}.
+         * @return this builder.
+         */
+        @NonNull
+        public Builder setOemManaged(@OemManaged int oemManaged) {
+            mOemManaged = oemManaged;
+            return this;
+        }
+
+        /**
+         * Check whether the match rule is requestable.
+         *
+         * @param matchRule the target match rule to be checked.
+         */
+        private static void assertRequestableMatchRule(final int matchRule) {
+            if (!isKnownMatchRule(matchRule)
+                    || matchRule == MATCH_PROXY
+                    || matchRule == MATCH_MOBILE_WILDCARD
+                    || matchRule == MATCH_WIFI_WILDCARD) {
+                throw new IllegalArgumentException("Invalid match rule: "
+                        + getMatchRuleName(matchRule));
+            }
+        }
+
+        private void assertRequestableParameters() {
+            // TODO: Check all the input are legitimate.
+        }
+
+        /**
+         * For backward compatibility, deduce match rule to a wildcard match rule
+         * if the Subscriber Ids are empty.
+         */
+        private int getWildcardDeducedMatchRule() {
+            if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) {
+                return MATCH_MOBILE_WILDCARD;
+            } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty()
+                    && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) {
+                return MATCH_WIFI_WILDCARD;
+            }
+            return mMatchRule;
+        }
+
+        /**
+         * Builds the instance of the NetworkTemplate.
+         *
+         * @return the built instance of NetworkTemplate.
+         */
+        @NonNull
+        public NetworkTemplate build() {
+            assertRequestableParameters();
+            final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty()
+                    ? SUBSCRIBER_ID_MATCH_RULE_ALL : SUBSCRIBER_ID_MATCH_RULE_EXACT;
+            return new NetworkTemplate(getWildcardDeducedMatchRule(),
+                    mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
+                    mMatchSubscriberIds.toArray(new String[0]),
+                    mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged,
+                    subscriberIdMatchRule);
+        }
+    }
 }
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index 6c597e2..0f21e55 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -16,10 +16,6 @@
 
 package android.net.nsd;
 
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.internal.util.Preconditions.checkStringNotEmpty;
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemService;
@@ -32,11 +28,13 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Protocol;
+
+import java.util.Objects;
 
 /**
  * The Network Service Discovery Manager class provides the API to discover services
@@ -175,65 +173,63 @@
      */
     public static final int NSD_STATE_ENABLED = 2;
 
-    private static final int BASE = Protocol.BASE_NSD_MANAGER;
+    /** @hide */
+    public static final int DISCOVER_SERVICES                       = 1;
+    /** @hide */
+    public static final int DISCOVER_SERVICES_STARTED               = 2;
+    /** @hide */
+    public static final int DISCOVER_SERVICES_FAILED                = 3;
+    /** @hide */
+    public static final int SERVICE_FOUND                           = 4;
+    /** @hide */
+    public static final int SERVICE_LOST                            = 5;
 
     /** @hide */
-    public static final int DISCOVER_SERVICES                       = BASE + 1;
+    public static final int STOP_DISCOVERY                          = 6;
     /** @hide */
-    public static final int DISCOVER_SERVICES_STARTED               = BASE + 2;
+    public static final int STOP_DISCOVERY_FAILED                   = 7;
     /** @hide */
-    public static final int DISCOVER_SERVICES_FAILED                = BASE + 3;
-    /** @hide */
-    public static final int SERVICE_FOUND                           = BASE + 4;
-    /** @hide */
-    public static final int SERVICE_LOST                            = BASE + 5;
+    public static final int STOP_DISCOVERY_SUCCEEDED                = 8;
 
     /** @hide */
-    public static final int STOP_DISCOVERY                          = BASE + 6;
+    public static final int REGISTER_SERVICE                        = 9;
     /** @hide */
-    public static final int STOP_DISCOVERY_FAILED                   = BASE + 7;
+    public static final int REGISTER_SERVICE_FAILED                 = 10;
     /** @hide */
-    public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 8;
+    public static final int REGISTER_SERVICE_SUCCEEDED              = 11;
 
     /** @hide */
-    public static final int REGISTER_SERVICE                        = BASE + 9;
+    public static final int UNREGISTER_SERVICE                      = 12;
     /** @hide */
-    public static final int REGISTER_SERVICE_FAILED                 = BASE + 10;
+    public static final int UNREGISTER_SERVICE_FAILED               = 13;
     /** @hide */
-    public static final int REGISTER_SERVICE_SUCCEEDED              = BASE + 11;
+    public static final int UNREGISTER_SERVICE_SUCCEEDED            = 14;
 
     /** @hide */
-    public static final int UNREGISTER_SERVICE                      = BASE + 12;
+    public static final int RESOLVE_SERVICE                         = 15;
     /** @hide */
-    public static final int UNREGISTER_SERVICE_FAILED               = BASE + 13;
+    public static final int RESOLVE_SERVICE_FAILED                  = 16;
     /** @hide */
-    public static final int UNREGISTER_SERVICE_SUCCEEDED            = BASE + 14;
+    public static final int RESOLVE_SERVICE_SUCCEEDED               = 17;
 
     /** @hide */
-    public static final int RESOLVE_SERVICE                         = BASE + 18;
-    /** @hide */
-    public static final int RESOLVE_SERVICE_FAILED                  = BASE + 19;
-    /** @hide */
-    public static final int RESOLVE_SERVICE_SUCCEEDED               = BASE + 20;
+    public static final int DAEMON_CLEANUP                          = 18;
 
     /** @hide */
-    public static final int DAEMON_CLEANUP                          = BASE + 21;
+    public static final int DAEMON_STARTUP                          = 19;
 
     /** @hide */
-    public static final int DAEMON_STARTUP                          = BASE + 22;
+    public static final int ENABLE                                  = 20;
+    /** @hide */
+    public static final int DISABLE                                 = 21;
 
     /** @hide */
-    public static final int ENABLE                                  = BASE + 24;
-    /** @hide */
-    public static final int DISABLE                                 = BASE + 25;
+    public static final int NATIVE_DAEMON_EVENT                     = 22;
 
     /** @hide */
-    public static final int NATIVE_DAEMON_EVENT                     = BASE + 26;
-
+    public static final int REGISTER_CLIENT                         = 23;
     /** @hide */
-    public static final int REGISTER_CLIENT                         = BASE + 27;
-    /** @hide */
-    public static final int UNREGISTER_CLIENT                       = BASE + 28;
+    public static final int UNREGISTER_CLIENT                       = 24;
 
     /** Dns based service discovery protocol */
     public static final int PROTOCOL_DNS_SD = 0x0001;
@@ -550,7 +546,9 @@
         final int key;
         synchronized (mMapLock) {
             int valueIndex = mListenerMap.indexOfValue(listener);
-            checkArgument(valueIndex == -1, "listener already in use");
+            if (valueIndex != -1) {
+                throw new IllegalArgumentException("listener already in use");
+            }
             key = nextListenerKey();
             mListenerMap.put(key, listener);
             mServiceMap.put(key, s);
@@ -569,7 +567,9 @@
         checkListener(listener);
         synchronized (mMapLock) {
             int valueIndex = mListenerMap.indexOfValue(listener);
-            checkArgument(valueIndex != -1, "listener not registered");
+            if (valueIndex == -1) {
+                throw new IllegalArgumentException("listener not registered");
+            }
             return mListenerMap.keyAt(valueIndex);
         }
     }
@@ -598,7 +598,9 @@
      */
     public void registerService(NsdServiceInfo serviceInfo, int protocolType,
             RegistrationListener listener) {
-        checkArgument(serviceInfo.getPort() > 0, "Invalid port number");
+        if (serviceInfo.getPort() <= 0) {
+            throw new IllegalArgumentException("Invalid port number");
+        }
         checkServiceInfo(serviceInfo);
         checkProtocol(protocolType);
         int key = putListener(listener, serviceInfo);
@@ -660,7 +662,9 @@
      * Cannot be null. Cannot be in use for an active service discovery.
      */
     public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
-        checkStringNotEmpty(serviceType, "Service type cannot be empty");
+        if (TextUtils.isEmpty(serviceType)) {
+            throw new IllegalArgumentException("Service type cannot be empty");
+        }
         checkProtocol(protocolType);
 
         NsdServiceInfo s = new NsdServiceInfo();
@@ -719,16 +723,22 @@
     }
 
     private static void checkListener(Object listener) {
-        checkNotNull(listener, "listener cannot be null");
+        Objects.requireNonNull(listener, "listener cannot be null");
     }
 
     private static void checkProtocol(int protocolType) {
-        checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol");
+        if (protocolType != PROTOCOL_DNS_SD) {
+            throw new IllegalArgumentException("Unsupported protocol");
+        }
     }
 
     private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
-        checkNotNull(serviceInfo, "NsdServiceInfo cannot be null");
-        checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty");
-        checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty");
+        Objects.requireNonNull(serviceInfo, "NsdServiceInfo cannot be null");
+        if (TextUtils.isEmpty(serviceInfo.getServiceName())) {
+            throw new IllegalArgumentException("Service name cannot be empty");
+        }
+        if (TextUtils.isEmpty(serviceInfo.getServiceType())) {
+            throw new IllegalArgumentException("Service type cannot be empty");
+        }
     }
 }
diff --git a/service-t/Sources.bp b/service-t/Sources.bp
index 6a64910..97dfb64 100644
--- a/service-t/Sources.bp
+++ b/service-t/Sources.bp
@@ -48,16 +48,42 @@
     ],
 }
 
+// IpSec related libraries.
+
+filegroup {
+    name: "services.connectivity-ipsec-sources",
+    srcs: [
+        "src/com/android/server/IpSecService.java",
+    ],
+    path: "src",
+    visibility: [
+        "//visibility:private",
+    ],
+}
+
+// Ethernet related libraries.
+
+filegroup {
+    name: "services.connectivity-ethernet-sources",
+    srcs: [
+        "src/com/android/server/net/IpConfigStore.java",
+    ],
+    path: "src",
+    visibility: [
+        "//frameworks/opt/net/ethernet",
+    ],
+}
+
 // Connectivity-T common libraries.
 
 filegroup {
     name: "services.connectivity-tiramisu-sources",
     srcs: [
+        ":services.connectivity-ethernet-sources",
+        ":services.connectivity-ipsec-sources",
         ":services.connectivity-netstats-sources",
         ":services.connectivity-nsd-sources",
     ],
     path: "src",
-    visibility: [
-        "//frameworks/base/services/core",
-    ],
-}
\ No newline at end of file
+    visibility: ["//frameworks/base/services/core"],
+}
diff --git a/services/core/java/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
similarity index 90%
rename from services/core/java/com/android/server/IpSecService.java
rename to service-t/src/com/android/server/IpSecService.java
index aeb8143..d1e432e 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -45,7 +45,6 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.TrafficStats;
-import android.net.util.NetdService;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
@@ -96,8 +95,6 @@
 public class IpSecService extends IIpSecService.Stub {
     private static final String TAG = "IpSecService";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private static final String NETD_SERVICE_NAME = "netd";
     private static final int[] ADDRESS_FAMILIES =
             new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
 
@@ -106,6 +103,8 @@
 
     @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10;
 
+    private final INetd mNetd;
+
     static {
         try {
             INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
@@ -119,6 +118,7 @@
 
     /* Binder context for this service */
     private final Context mContext;
+    private final Dependencies mDeps;
 
     /**
      * The next non-repeating global ID for tracking resources between users, this service, and
@@ -129,23 +129,24 @@
     @GuardedBy("IpSecService.this")
     private int mNextResourceId = 1;
 
-    interface IpSecServiceConfiguration {
-        INetd getNetdInstance() throws RemoteException;
-
-        static IpSecServiceConfiguration GETSRVINSTANCE =
-                new IpSecServiceConfiguration() {
-                    @Override
-                    public INetd getNetdInstance() throws RemoteException {
-                        final INetd netd = NetdService.getInstance();
-                        if (netd == null) {
-                            throw new RemoteException("Failed to Get Netd Instance");
-                        }
-                        return netd;
-                    }
-                };
+    /**
+     * Dependencies of IpSecService, for injection in tests.
+     */
+    @VisibleForTesting
+    public static class Dependencies {
+        /**
+         * Get a reference to INetd.
+         */
+        public INetd getNetdInstance(Context context) throws RemoteException {
+            final INetd netd = INetd.Stub.asInterface((IBinder)
+                    context.getSystemService(Context.NETD_SERVICE));
+            if (netd == null) {
+                throw new RemoteException("Failed to Get Netd Instance");
+            }
+            return netd;
+        }
     }
 
-    private final IpSecServiceConfiguration mSrvConfig;
     final UidFdTagger mUidFdTagger;
 
     /**
@@ -491,8 +492,8 @@
      * <p>This class associates kernel resources with the UID that owns and controls them.
      */
     private abstract class OwnedResourceRecord implements IResource {
-        final int pid;
-        final int uid;
+        final int mPid;
+        final int mUid;
         protected final int mResourceId;
 
         OwnedResourceRecord(int resourceId) {
@@ -501,8 +502,8 @@
                 throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
             }
             mResourceId = resourceId;
-            pid = Binder.getCallingPid();
-            uid = Binder.getCallingUid();
+            mPid = Binder.getCallingPid();
+            mUid = Binder.getCallingUid();
 
             getResourceTracker().take();
         }
@@ -512,7 +513,7 @@
 
         /** Convenience method; retrieves the user resource record for the stored UID. */
         protected UserRecord getUserRecord() {
-            return mUserResourceTracker.getUserRecord(uid);
+            return mUserResourceTracker.getUserRecord(mUid);
         }
 
         @Override
@@ -527,9 +528,9 @@
                     .append("{mResourceId=")
                     .append(mResourceId)
                     .append(", pid=")
-                    .append(pid)
+                    .append(mPid)
                     .append(", uid=")
-                    .append(uid)
+                    .append(mUid)
                     .append("}")
                     .toString();
         }
@@ -545,7 +546,7 @@
         SparseArray<RefcountedResource<T>> mArray = new SparseArray<>();
         private final String mTypeName;
 
-        public RefcountedResourceArray(String typeName) {
+        RefcountedResourceArray(String typeName) {
             this.mTypeName = typeName;
         }
 
@@ -625,16 +626,14 @@
         public void freeUnderlyingResources() {
             int spi = mSpi.getSpi();
             try {
-                mSrvConfig
-                        .getNetdInstance()
-                        .ipSecDeleteSecurityAssociation(
-                                uid,
-                                mConfig.getSourceAddress(),
-                                mConfig.getDestinationAddress(),
-                                spi,
-                                mConfig.getMarkValue(),
-                                mConfig.getMarkMask(),
-                                mConfig.getXfrmInterfaceId());
+                mNetd.ipSecDeleteSecurityAssociation(
+                        mUid,
+                        mConfig.getSourceAddress(),
+                        mConfig.getDestinationAddress(),
+                        spi,
+                        mConfig.getMarkValue(),
+                        mConfig.getMarkMask(),
+                        mConfig.getXfrmInterfaceId());
             } catch (RemoteException | ServiceSpecificException e) {
                 Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e);
             }
@@ -681,7 +680,8 @@
 
         private boolean mOwnedByTransform = false;
 
-        SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) {
+        SpiRecord(int resourceId, String sourceAddress,
+                String destinationAddress, int spi) {
             super(resourceId);
             mSourceAddress = sourceAddress;
             mDestinationAddress = destinationAddress;
@@ -693,11 +693,9 @@
         public void freeUnderlyingResources() {
             try {
                 if (!mOwnedByTransform) {
-                    mSrvConfig
-                            .getNetdInstance()
-                            .ipSecDeleteSecurityAssociation(
-                                    uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
-                                    0 /* mask */, 0 /* if_id */);
+                    mNetd.ipSecDeleteSecurityAssociation(
+                            mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */,
+                            0 /* mask */, 0 /* if_id */);
                 }
             } catch (ServiceSpecificException | RemoteException e) {
                 Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e);
@@ -844,19 +842,18 @@
             //       Teardown VTI
             //       Delete global policies
             try {
-                final INetd netd = mSrvConfig.getNetdInstance();
-                netd.ipSecRemoveTunnelInterface(mInterfaceName);
+                mNetd.ipSecRemoveTunnelInterface(mInterfaceName);
 
                 for (int selAddrFamily : ADDRESS_FAMILIES) {
-                    netd.ipSecDeleteSecurityPolicy(
-                            uid,
+                    mNetd.ipSecDeleteSecurityPolicy(
+                            mUid,
                             selAddrFamily,
                             IpSecManager.DIRECTION_OUT,
                             mOkey,
                             0xffffffff,
                             mIfId);
-                    netd.ipSecDeleteSecurityPolicy(
-                            uid,
+                    mNetd.ipSecDeleteSecurityPolicy(
+                            mUid,
                             selAddrFamily,
                             IpSecManager.DIRECTION_IN,
                             mIkey,
@@ -1012,29 +1009,28 @@
      * @param context Binder context for this service
      */
     private IpSecService(Context context) {
-        this(context, IpSecServiceConfiguration.GETSRVINSTANCE);
+        this(context, new Dependencies());
     }
 
     static IpSecService create(Context context)
             throws InterruptedException {
         final IpSecService service = new IpSecService(context);
-        service.connectNativeNetdService();
         return service;
     }
 
     @NonNull
     private AppOpsManager getAppOpsManager() {
         AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-        if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps");
+        if (appOps == null) throw new RuntimeException("System Server couldn't get AppOps");
         return appOps;
     }
 
     /** @hide */
     @VisibleForTesting
-    public IpSecService(Context context, IpSecServiceConfiguration config) {
+    public IpSecService(Context context, Dependencies deps) {
         this(
                 context,
-                config,
+                deps,
                 (fd, uid) -> {
                     try {
                         TrafficStats.setThreadStatsUid(uid);
@@ -1047,13 +1043,18 @@
 
     /** @hide */
     @VisibleForTesting
-    public IpSecService(Context context, IpSecServiceConfiguration config,
-            UidFdTagger uidFdTagger) {
+    public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) {
         mContext = context;
-        mSrvConfig = config;
+        mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
         mUidFdTagger = uidFdTagger;
+        try {
+            mNetd = mDeps.getNetdInstance(mContext);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
+    /** Called by system server when system is ready. */
     public void systemReady() {
         if (isNetdAlive()) {
             Log.d(TAG, "IpSecService is ready");
@@ -1062,25 +1063,12 @@
         }
     }
 
-    private void connectNativeNetdService() {
-        // Avoid blocking the system server to do this
-        new Thread() {
-            @Override
-            public void run() {
-                synchronized (IpSecService.this) {
-                    NetdService.get(NETD_FETCH_TIMEOUT_MS);
-                }
-            }
-        }.start();
-    }
-
     synchronized boolean isNetdAlive() {
         try {
-            final INetd netd = mSrvConfig.getNetdInstance();
-            if (netd == null) {
+            if (mNetd == null) {
                 return false;
             }
-            return netd.isAlive();
+            return mNetd.isAlive();
         } catch (RemoteException re) {
             return false;
         }
@@ -1141,15 +1129,13 @@
                         IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
             }
 
-            spi =
-                    mSrvConfig
-                            .getNetdInstance()
-                            .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
+            spi = mNetd.ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi);
             Log.d(TAG, "Allocated SPI " + spi);
             userRecord.mSpiRecords.put(
                     resourceId,
                     new RefcountedResource<SpiRecord>(
-                            new SpiRecord(resourceId, "", destinationAddress, spi), binder));
+                            new SpiRecord(resourceId, "",
+                            destinationAddress, spi), binder));
         } catch (ServiceSpecificException e) {
             if (e.errorCode == OsConstants.ENOENT) {
                 return new IpSecSpiResponse(
@@ -1229,7 +1215,7 @@
          * <p>Since the socket is created on behalf of an unprivileged application, all traffic
          * should be accounted to the UID of the unprivileged application.
          */
-        public void tag(FileDescriptor fd, int uid) throws IOException;
+        void tag(FileDescriptor fd, int uid) throws IOException;
     }
 
     /**
@@ -1266,8 +1252,7 @@
                     OsConstants.UDP_ENCAP,
                     OsConstants.UDP_ENCAP_ESPINUDP);
 
-            mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(
-                        new ParcelFileDescriptor(sockFd), callingUid);
+            mNetd.ipSecSetEncapSocketOwner(new ParcelFileDescriptor(sockFd), callingUid);
             if (port != 0) {
                 Log.v(TAG, "Binding to port " + port);
                 Os.bind(sockFd, INADDR_ANY, port);
@@ -1329,16 +1314,15 @@
             //       Create VTI
             //       Add inbound/outbound global policies
             //              (use reqid = 0)
-            final INetd netd = mSrvConfig.getNetdInstance();
-            netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
+            mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
 
             BinderUtils.withCleanCallingIdentity(() -> {
-                NetdUtils.setInterfaceUp(netd, intfName);
+                NetdUtils.setInterfaceUp(mNetd, intfName);
             });
 
             for (int selAddrFamily : ADDRESS_FAMILIES) {
                 // Always send down correct local/remote addresses for template.
-                netd.ipSecAddSecurityPolicy(
+                mNetd.ipSecAddSecurityPolicy(
                         callerUid,
                         selAddrFamily,
                         IpSecManager.DIRECTION_OUT,
@@ -1348,7 +1332,7 @@
                         okey,
                         0xffffffff,
                         resourceId);
-                netd.ipSecAddSecurityPolicy(
+                mNetd.ipSecAddSecurityPolicy(
                         callerUid,
                         selAddrFamily,
                         IpSecManager.DIRECTION_IN,
@@ -1368,7 +1352,7 @@
                 //
                 // This is necessary only on the tunnel interface, and not any the interface to
                 // which traffic will be forwarded to.
-                netd.ipSecAddSecurityPolicy(
+                mNetd.ipSecAddSecurityPolicy(
                         callerUid,
                         selAddrFamily,
                         IpSecManager.DIRECTION_FWD,
@@ -1425,12 +1409,10 @@
         try {
             // We can assume general validity of the IP address, since we get them as a
             // LinkAddress, which does some validation.
-            mSrvConfig
-                    .getNetdInstance()
-                    .interfaceAddAddress(
-                            tunnelInterfaceInfo.mInterfaceName,
-                            localAddr.getAddress().getHostAddress(),
-                            localAddr.getPrefixLength());
+            mNetd.interfaceAddAddress(
+                    tunnelInterfaceInfo.mInterfaceName,
+                    localAddr.getAddress().getHostAddress(),
+                    localAddr.getPrefixLength());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1454,9 +1436,7 @@
         try {
             // We can assume general validity of the IP address, since we get them as a
             // LinkAddress, which does some validation.
-            mSrvConfig
-                    .getNetdInstance()
-                    .interfaceDelAddress(
+            mNetd.interfaceDelAddress(
                             tunnelInterfaceInfo.mInterfaceName,
                             localAddr.getAddress().getHostAddress(),
                             localAddr.getPrefixLength());
@@ -1669,30 +1649,28 @@
             cryptName = crypt.getName();
         }
 
-        mSrvConfig
-                .getNetdInstance()
-                .ipSecAddSecurityAssociation(
-                        Binder.getCallingUid(),
-                        c.getMode(),
-                        c.getSourceAddress(),
-                        c.getDestinationAddress(),
-                        (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
-                        spiRecord.getSpi(),
-                        c.getMarkValue(),
-                        c.getMarkMask(),
-                        (auth != null) ? auth.getName() : "",
-                        (auth != null) ? auth.getKey() : new byte[] {},
-                        (auth != null) ? auth.getTruncationLengthBits() : 0,
-                        cryptName,
-                        (crypt != null) ? crypt.getKey() : new byte[] {},
-                        (crypt != null) ? crypt.getTruncationLengthBits() : 0,
-                        (authCrypt != null) ? authCrypt.getName() : "",
-                        (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
-                        (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
-                        encapType,
-                        encapLocalPort,
-                        encapRemotePort,
-                        c.getXfrmInterfaceId());
+        mNetd.ipSecAddSecurityAssociation(
+                Binder.getCallingUid(),
+                c.getMode(),
+                c.getSourceAddress(),
+                c.getDestinationAddress(),
+                (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0,
+                spiRecord.getSpi(),
+                c.getMarkValue(),
+                c.getMarkMask(),
+                (auth != null) ? auth.getName() : "",
+                (auth != null) ? auth.getKey() : new byte[] {},
+                (auth != null) ? auth.getTruncationLengthBits() : 0,
+                cryptName,
+                (crypt != null) ? crypt.getKey() : new byte[] {},
+                (crypt != null) ? crypt.getTruncationLengthBits() : 0,
+                (authCrypt != null) ? authCrypt.getName() : "",
+                (authCrypt != null) ? authCrypt.getKey() : new byte[] {},
+                (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
+                encapType,
+                encapLocalPort,
+                encapRemotePort,
+                c.getXfrmInterfaceId());
     }
 
     /**
@@ -1771,7 +1749,7 @@
         TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
 
         // TODO: make this a function.
-        if (info.pid != getCallingPid() || info.uid != callingUid) {
+        if (info.mPid != getCallingPid() || info.mUid != callingUid) {
             throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
         }
 
@@ -1781,15 +1759,13 @@
                 c.getMode() == IpSecTransform.MODE_TRANSPORT,
                 "Transform mode was not Transport mode; cannot be applied to a socket");
 
-        mSrvConfig
-                .getNetdInstance()
-                .ipSecApplyTransportModeTransform(
-                        socket,
-                        callingUid,
-                        direction,
-                        c.getSourceAddress(),
-                        c.getDestinationAddress(),
-                        info.getSpiRecord().getSpi());
+        mNetd.ipSecApplyTransportModeTransform(
+                socket,
+                callingUid,
+                direction,
+                c.getSourceAddress(),
+                c.getDestinationAddress(),
+                info.getSpiRecord().getSpi());
     }
 
     /**
@@ -1801,9 +1777,7 @@
     @Override
     public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
             throws RemoteException {
-        mSrvConfig
-                .getNetdInstance()
-                .ipSecRemoveTransportModeTransform(socket);
+        mNetd.ipSecRemoveTransportModeTransform(socket);
     }
 
     /**
@@ -1878,18 +1852,16 @@
 
             // Always update the policy with the relevant XFRM_IF_ID
             for (int selAddrFamily : ADDRESS_FAMILIES) {
-                mSrvConfig
-                        .getNetdInstance()
-                        .ipSecUpdateSecurityPolicy(
-                                callingUid,
-                                selAddrFamily,
-                                direction,
-                                transformInfo.getConfig().getSourceAddress(),
-                                transformInfo.getConfig().getDestinationAddress(),
-                                spi, // If outbound, also add SPI to the policy.
-                                mark, // Must always set policy mark; ikey/okey for VTIs
-                                0xffffffff,
-                                c.getXfrmInterfaceId());
+                mNetd.ipSecUpdateSecurityPolicy(
+                        callingUid,
+                        selAddrFamily,
+                        direction,
+                        transformInfo.getConfig().getSourceAddress(),
+                        transformInfo.getConfig().getDestinationAddress(),
+                        spi, // If outbound, also add SPI to the policy.
+                        mark, // Must always set policy mark; ikey/okey for VTIs
+                        0xffffffff,
+                        c.getXfrmInterfaceId());
             }
 
             // Update SA with tunnel mark (ikey or okey based on direction)
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/service-t/src/com/android/server/net/IpConfigStore.java
similarity index 95%
rename from services/core/java/com/android/server/net/IpConfigStore.java
rename to service-t/src/com/android/server/net/IpConfigStore.java
index d17dbde..3a9a544 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/service-t/src/com/android/server/net/IpConfigStore.java
@@ -44,6 +44,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * This class provides an API to store and manage L3 network IP configuration.
+ */
 public class IpConfigStore {
     private static final String TAG = "IpConfigStore";
     private static final boolean DBG = false;
@@ -78,6 +81,9 @@
         return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION);
     }
 
+    /**
+     *  Write the IP configuration with the given parameters to {@link DataOutputStream}.
+     */
     @VisibleForTesting
     public static boolean writeConfig(DataOutputStream out, String configKey,
                                 IpConfiguration config, int version) throws IOException {
@@ -154,10 +160,10 @@
                     break;
                 case UNASSIGNED:
                     /* Ignore */
-                        break;
-                    default:
-                        loge("Ignore invalid proxy settings while writing");
-                        break;
+                    break;
+                default:
+                    loge("Ignore invalid proxy settings while writing");
+                    break;
             }
 
             if (written) {
@@ -177,7 +183,7 @@
     }
 
     /**
-     * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
+     * @deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead.
      * New method uses string as network identifier which could be interface name or MAC address or
      * other token.
      */
@@ -186,22 +192,28 @@
                                               final SparseArray<IpConfiguration> networks) {
         mWriter.write(filePath, out -> {
             out.writeInt(IPCONFIG_FILE_VERSION);
-            for(int i = 0; i < networks.size(); i++) {
+            for (int i = 0; i < networks.size(); i++) {
                 writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i));
             }
         });
     }
 
+    /**
+     *  Write the IP configuration associated to the target networks to the destination path.
+     */
     public void writeIpConfigurations(String filePath,
                                       ArrayMap<String, IpConfiguration> networks) {
         mWriter.write(filePath, out -> {
             out.writeInt(IPCONFIG_FILE_VERSION);
-            for(int i = 0; i < networks.size(); i++) {
+            for (int i = 0; i < networks.size(); i++) {
                 writeConfig(out, networks.keyAt(i), networks.valueAt(i));
             }
         });
     }
 
+    /**
+     * Read the IP configuration from the destination path to {@link BufferedInputStream}.
+     */
     public static ArrayMap<String, IpConfiguration> readIpConfigurations(String filePath) {
         BufferedInputStream bufferedInputStream;
         try {
@@ -215,7 +227,7 @@
         return readIpConfigurations(bufferedInputStream);
     }
 
-    /** @Deprecated use {@link #readIpConfigurations(String)} */
+    /** @deprecated use {@link #readIpConfigurations(String)} */
     @Deprecated
     public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
         BufferedInputStream bufferedInputStream;
@@ -230,7 +242,7 @@
         return readIpAndProxyConfigurations(bufferedInputStream);
     }
 
-    /** @Deprecated use {@link #readIpConfigurations(InputStream)} */
+    /** @deprecated use {@link #readIpConfigurations(InputStream)} */
     @Deprecated
     public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
             InputStream inputStream) {
@@ -420,7 +432,7 @@
             if (in != null) {
                 try {
                     in.close();
-                } catch (Exception e) {}
+                } catch (Exception e) { }
             }
         }