diff --git a/Android.bp b/Android.bp
index 80b4c76..8c5a855 100644
--- a/Android.bp
+++ b/Android.bp
@@ -271,8 +271,6 @@
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
-            // TODO: remove when moved to the below package
-            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
             "packages/modules/Media/apex/aidl/stable",
         ],
@@ -519,8 +517,6 @@
         include_dirs: [
             "frameworks/av/aidl",
             "frameworks/native/libs/permission/aidl",
-            // TODO: remove when moved to the below package
-            "frameworks/base/packages/ConnectivityT/framework-t/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
         ],
     },
diff --git a/core/api/current.txt b/core/api/current.txt
index a09a359..8f74ae1 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -42283,8 +42283,8 @@
     method public boolean isEnabled();
     method public boolean isSimPortAvailable(int);
     method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
-    method @Deprecated @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
-    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccManager.ResultListener);
+    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, int, @NonNull android.app.PendingIntent);
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
     field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
     field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
@@ -42303,6 +42303,7 @@
     field public static final int ERROR_INSTALL_PROFILE = 10009; // 0x2719
     field public static final int ERROR_INVALID_ACTIVATION_CODE = 10001; // 0x2711
     field public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002; // 0x2712
+    field public static final int ERROR_INVALID_PORT = 10017; // 0x2721
     field public static final int ERROR_INVALID_RESPONSE = 10015; // 0x271f
     field public static final int ERROR_NO_PROFILES_AVAILABLE = 10013; // 0x271d
     field public static final int ERROR_OPERATION_BUSY = 10016; // 0x2720
@@ -42330,10 +42331,6 @@
     field public static final int OPERATION_SYSTEM = 1; // 0x1
   }
 
-  public static interface EuiccManager.ResultListener {
-    method public void onComplete(int, @Nullable android.content.Intent);
-  }
-
 }
 
 package android.telephony.gsm {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d5be20f..0a5b91f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9665,6 +9665,7 @@
     field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
     field public static final String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
     field public static final String EXTRA_RESOLUTION_PORT_INDEX = "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
+    field public static final String EXTRA_RESOLUTION_USE_PORT_INDEX = "android.service.euicc.extra.RESOLUTION_USE_PORT_INDEX";
     field public static final String EXTRA_RESOLVABLE_ERRORS = "android.service.euicc.extra.RESOLVABLE_ERRORS";
     field public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1; // 0x1
     field public static final int RESOLVABLE_ERROR_POLICY_RULES = 2; // 0x2
@@ -11596,7 +11597,6 @@
   }
 
   public class TelephonyManager {
-    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -11697,7 +11697,6 @@
     method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -11857,10 +11856,6 @@
     method public default void onCarrierServiceChanged(@Nullable String, int);
   }
 
-  @Deprecated public static interface TelephonyManager.CarrierPrivilegesListener {
-    method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
-  }
-
   public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
     ctor public TelephonyManager.ModemActivityInfoException(int);
     method public int getErrorCode();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 8f2417b..df95f8f 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -445,7 +445,7 @@
 
     void requestInteractiveBugReport();
     void requestFullBugReport();
-    void requestRemoteBugReport();
+    void requestRemoteBugReport(long nonce);
     boolean launchBugReportHandlerApp();
     List<String> getBugreportWhitelistedPackages();
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 42e28a9..b03bbc6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -499,6 +499,14 @@
             "android.intent.extra.REMOTE_BUGREPORT_HASH";
 
     /**
+     * Extra for shared bugreport's nonce in long integer type.
+     *
+     * @hide
+     */
+    public static final String EXTRA_REMOTE_BUGREPORT_NONCE =
+            "android.intent.extra.REMOTE_BUGREPORT_NONCE";
+
+    /**
      * Extra for remote bugreport notification shown type.
      *
      * @hide
diff --git a/core/java/android/hardware/location/OWNERS b/core/java/android/hardware/location/OWNERS
index bd40409..747f909 100644
--- a/core/java/android/hardware/location/OWNERS
+++ b/core/java/android/hardware/location/OWNERS
@@ -1,9 +1,12 @@
 # Bug component: 880425
 
-mstogaitis@google.com
-wyattriley@google.com
+dnchrist@google.com
 etn@google.com
-weiwa@google.com
+lifu@google.com
+mstogaitis@google.com
+sooniln@google.com
+wyattriley@google.com
+yuhany@google.com
 
 # ContextHub team
 per-file *ContextHub*,*NanoApp* = file:platform/system/chre:/OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 9b03172..08ab73b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2163,7 +2163,7 @@
      *   sized with the exact size of dimensions.
      *
      * @see #readFixedArray
-     * @see #createFixedArray
+     * @see #createFixedArray createFixedArray(Class&lt;T&gt;, Parcelable.Creator&lt;S&gt;, int...)
      * @see #writeBooleanArray
      * @see #writeByteArray
      * @see #writeCharArray
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 2d40219..0919e5b 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -538,6 +538,13 @@
     public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot";
 
     /**
+     * Definitions for voice interaction related functions.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction";
+
+    /**
      * List of namespaces which can be read without READ_DEVICE_CONFIG permission
      *
      * @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 5b59b21..5ee4131 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5310,6 +5310,13 @@
         public static final String COLUMN_PROFILE_CLASS = "profile_class";
 
         /**
+         * TelephonyProvider column name for the port index of the active UICC port.
+         * <P>Type: INTEGER (int)</P>
+         * @hide
+         */
+        public static final String COLUMN_PORT_INDEX = "port_index";
+
+        /**
          * A testing profile can be pre-loaded or downloaded onto
          * the eUICC and provides connectivity to test equipment
          * for the purpose of testing the device and the eUICC. It
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
index 0cb69a4..61fd041 100644
--- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -167,10 +167,7 @@
     protected WrappedApplicationKey(Parcel in) {
         mAlias = in.readString();
         mEncryptedKeyMaterial = in.createByteArray();
-        // Check if there is still data to be read.
-        if (in.dataAvail() > 0) {
-            mMetadata = in.createByteArray();
-        }
+        mMetadata = in.createByteArray();
     }
 
     @Override
diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java
index 7ed733c..9d648a6 100644
--- a/core/java/android/service/gatekeeper/GateKeeperResponse.java
+++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java
@@ -105,7 +105,7 @@
             dest.writeInt(mTimeout);
         } else if (mResponseCode == RESPONSE_OK) {
             dest.writeInt(mShouldReEnroll ? 1 : 0);
-            if (mPayload != null) {
+            if (mPayload != null && mPayload.length > 0) {
                 dest.writeInt(mPayload.length);
                 dest.writeByteArray(mPayload);
             } else {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 0d8b1f8..9c7f23e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -38,7 +38,6 @@
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
-import android.telephony.TelephonyManager.CarrierPrivilegesListener;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.util.ArraySet;
@@ -1262,149 +1261,52 @@
                 pkgName, attributionTag, callback, new int[0], notifyNow);
     }
 
-    // TODO(b/216549778): Remove listener logic once all clients switch to CarrierPrivilegesCallback
     private static class CarrierPrivilegesCallbackWrapper extends ICarrierPrivilegesCallback.Stub
             implements ListenerExecutor {
-        // Either mListener or mCallback may be null, never both
-        @Nullable private final WeakReference<CarrierPrivilegesListener> mListener;
-        @Nullable private final WeakReference<CarrierPrivilegesCallback> mCallback;
+        @NonNull private final WeakReference<CarrierPrivilegesCallback> mCallback;
         @NonNull private final Executor mExecutor;
 
         CarrierPrivilegesCallbackWrapper(
                 @NonNull CarrierPrivilegesCallback callback, @NonNull Executor executor) {
-            mListener = null;
             mCallback = new WeakReference<>(callback);
             mExecutor = executor;
         }
 
-        CarrierPrivilegesCallbackWrapper(
-                @NonNull CarrierPrivilegesListener listener, @NonNull Executor executor) {
-            mListener = new WeakReference<>(listener);
-            mCallback = null;
-            mExecutor = executor;
-        }
-
         @Override
         public void onCarrierPrivilegesChanged(
                 @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids) {
-            if (mListener != null) {
-                Binder.withCleanCallingIdentity(
-                        () ->
-                                executeSafely(
-                                        mExecutor,
-                                        mListener::get,
-                                        cpl ->
-                                                cpl.onCarrierPrivilegesChanged(
-                                                        privilegedPackageNames, privilegedUids)));
-            }
-
-            if (mCallback != null) {
-                // AIDL interface does not support Set, keep the List/Array and translate them here
-                Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames);
-                Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect(
-                        Collectors.toSet());
-                Binder.withCleanCallingIdentity(
-                        () ->
-                                executeSafely(
-                                        mExecutor,
-                                        mCallback::get,
-                                        cpc ->
-                                                cpc.onCarrierPrivilegesChanged(
-                                                        privilegedPkgNamesSet, privilegedUidsSet)));
-            }
+            // AIDL interface does not support Set, keep the List/Array and translate them here
+            Set<String> privilegedPkgNamesSet = Set.copyOf(privilegedPackageNames);
+            Set<Integer> privilegedUidsSet = Arrays.stream(privilegedUids).boxed().collect(
+                    Collectors.toSet());
+            Binder.withCleanCallingIdentity(
+                    () ->
+                            executeSafely(
+                                    mExecutor,
+                                    mCallback::get,
+                                    cpc ->
+                                            cpc.onCarrierPrivilegesChanged(
+                                                    privilegedPkgNamesSet, privilegedUidsSet)));
         }
 
         @Override
         public void onCarrierServiceChanged(@Nullable String packageName, int uid) {
-            if (mCallback != null) {
-                Binder.withCleanCallingIdentity(
-                        () ->
-                                executeSafely(
-                                        mExecutor,
-                                        mCallback::get,
-                                        cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
-            }
+            Binder.withCleanCallingIdentity(
+                    () ->
+                            executeSafely(
+                                    mExecutor,
+                                    mCallback::get,
+                                    cpc -> cpc.onCarrierServiceChanged(packageName, uid)));
         }
     }
 
-    // TODO(b/216549778): Change the map key to CarrierPrivilegesCallback once all clients switch to
-    // CarrierPrivilegesCallback. Before that, the key is either CarrierPrivilegesCallback or
-    // CarrierPrivilegesListener, no logic actually depends on the type.
     @NonNull
     @GuardedBy("sCarrierPrivilegeCallbacks")
-    private static final WeakHashMap<Object,  WeakReference<CarrierPrivilegesCallbackWrapper>>
+    private static final WeakHashMap<CarrierPrivilegesCallback,
+            WeakReference<CarrierPrivilegesCallbackWrapper>>
             sCarrierPrivilegeCallbacks = new WeakHashMap<>();
 
     /**
-     * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
-     * receive callbacks when the set of packages with carrier privileges changes. The callback will
-     * immediately be called with the latest state.
-     *
-     * @param logicalSlotIndex The SIM slot to listen on
-     * @param executor The executor where {@code listener} will be invoked
-     * @param listener The callback to register
-     *
-     * @deprecated Use {@link #addCarrierPrivilegesCallback} instead. This API will be removed
-     * prior to API finalization.
-     */
-    @Deprecated
-    public void addCarrierPrivilegesListener(
-            int logicalSlotIndex,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull CarrierPrivilegesListener listener) {
-        if (listener == null || executor == null) {
-            throw new IllegalArgumentException("listener and executor must be non-null");
-        }
-        synchronized (sCarrierPrivilegeCallbacks) {
-            WeakReference<CarrierPrivilegesCallbackWrapper> existing =
-                    sCarrierPrivilegeCallbacks.get(listener);
-            if (existing != null && existing.get() != null) {
-                Log.d(TAG, "addCarrierPrivilegesListener: listener already registered");
-                return;
-            }
-            CarrierPrivilegesCallbackWrapper wrapper =
-                    new CarrierPrivilegesCallbackWrapper(listener, executor);
-            sCarrierPrivilegeCallbacks.put(listener, new WeakReference<>(wrapper));
-            try {
-                sRegistry.addCarrierPrivilegesCallback(
-                        logicalSlotIndex,
-                        wrapper,
-                        mContext.getOpPackageName(),
-                        mContext.getAttributionTag());
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
-     * Unregisters a {@link CarrierPrivilegesListener}.
-     *
-     * @param listener The callback to unregister
-     *
-     * @deprecated Use {@link #removeCarrierPrivilegesCallback} instead. The callback will prior
-     * to API finalization.
-     */
-    @Deprecated
-    public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must be non-null");
-        }
-        synchronized (sCarrierPrivilegeCallbacks) {
-            WeakReference<CarrierPrivilegesCallbackWrapper> ref =
-                    sCarrierPrivilegeCallbacks.remove(listener);
-            if (ref == null) return;
-            CarrierPrivilegesCallbackWrapper wrapper = ref.get();
-            if (wrapper == null) return;
-            try {
-                sRegistry.removeCarrierPrivilegesCallback(wrapper, mContext.getOpPackageName());
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
      * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
      * receive callbacks when the set of packages with carrier privileges changes. The callback will
      * immediately be called with the latest state.
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index b166fa6..407648d 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -10,6 +10,7 @@
 jjaggi@google.com
 roosa@google.com
 jreck@google.com
+siyamed@google.com
 
 # Autofill
 per-file ViewStructure.java = file:/core/java/android/service/autofill/OWNERS
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index efffa2b..aba79d5 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -171,8 +171,9 @@
     public void setSystemBarsAppearance(int appearance, int mask) {
         mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED;
         final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags;
-        if (insetsFlags.appearance != appearance) {
-            insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
+        final int newAppearance = (insetsFlags.appearance & ~mask) | (appearance & mask);
+        if (insetsFlags.appearance != newAppearance) {
+            insetsFlags.appearance = newAppearance;
             mViewRoot.mWindowAttributesChanged = true;
             mViewRoot.scheduleTraversals();
         }
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index cdff585..9d625c0 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -138,6 +138,11 @@
         "dagger2",
         "jsr330",
     ],
+    libs: [
+        // Soong fails to automatically add this dependency because all the
+        // *.kt sources are inside a filegroup.
+        "kotlin-annotations",
+    ],
     kotlincflags: ["-Xjvm-default=enable"],
     manifest: "AndroidManifest.xml",
     plugins: ["dagger2-compiler"],
diff --git a/location/java/android/location/OWNERS b/location/java/android/location/OWNERS
index 6032144..b5c970a 100644
--- a/location/java/android/location/OWNERS
+++ b/location/java/android/location/OWNERS
@@ -1,6 +1,9 @@
 # Bug component: 880425
 
+dnchrist@google.com
+etn@google.com
+lifu@google.com
+mstogaitis@google.com
 sooniln@google.com
 wyattriley@google.com
 yuhany@google.com
-weiwa@google.com
diff --git a/packages/ConnectivityT/OWNERS b/packages/ConnectivityT/OWNERS
deleted file mode 100644
index adbcd4b..0000000
--- a/packages/ConnectivityT/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# OWNERS block for code move: b/222234190
-reminv@google.com
-
-# file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
-# per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
deleted file mode 100644
index bc27852..0000000
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ /dev/null
@@ -1,205 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // See: http://go/android-license-faq
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// NetworkStats related libraries.
-
-filegroup {
-    name: "framework-connectivity-netstats-internal-sources",
-    srcs: [
-        "src/android/app/usage/*.java",
-        "src/android/net/DataUsageRequest.*",
-        "src/android/net/INetworkStatsService.aidl",
-        "src/android/net/INetworkStatsSession.aidl",
-        "src/android/net/NetworkIdentity.java",
-        "src/android/net/NetworkIdentitySet.java",
-        "src/android/net/NetworkStateSnapshot.*",
-        "src/android/net/NetworkStats.*",
-        "src/android/net/NetworkStatsAccess.*",
-        "src/android/net/NetworkStatsCollection.*",
-        "src/android/net/NetworkStatsHistory.*",
-        "src/android/net/NetworkTemplate.*",
-        "src/android/net/TrafficStats.java",
-        "src/android/net/UnderlyingNetworkInfo.*",
-        "src/android/net/netstats/**/*.*",
-    ],
-    path: "src",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-filegroup {
-    name: "framework-connectivity-netstats-aidl-export-sources",
-    srcs: [
-        "aidl-export/android/net/NetworkStats.aidl",
-        "aidl-export/android/net/NetworkTemplate.aidl",
-    ],
-    path: "aidl-export",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-filegroup {
-    name: "framework-connectivity-netstats-sources",
-    srcs: [
-        ":framework-connectivity-netstats-internal-sources",
-        ":framework-connectivity-netstats-aidl-export-sources",
-    ],
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-// Nsd related libraries.
-
-filegroup {
-    name: "framework-connectivity-nsd-internal-sources",
-    srcs: [
-        "src/android/net/nsd/*.aidl",
-        "src/android/net/nsd/*.java",
-    ],
-    path: "src",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-filegroup {
-    name: "framework-connectivity-nsd-aidl-export-sources",
-    srcs: [
-        "aidl-export/android/net/nsd/*.aidl",
-    ],
-    path: "aidl-export",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-filegroup {
-    name: "framework-connectivity-nsd-sources",
-    srcs: [
-        ":framework-connectivity-nsd-internal-sources",
-        ":framework-connectivity-nsd-aidl-export-sources",
-    ],
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-// 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/EthernetNetworkManagementException.java",
-        "src/android/net/EthernetNetworkManagementException.aidl",
-        "src/android/net/EthernetNetworkSpecifier.java",
-        "src/android/net/EthernetNetworkUpdateRequest.java",
-        "src/android/net/EthernetNetworkUpdateRequest.aidl",
-        "src/android/net/IEthernetManager.aidl",
-        "src/android/net/IEthernetServiceListener.aidl",
-        "src/android/net/INetworkInterfaceOutcomeReceiver.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",
-    ],
-}
-
-// TODO: remove this empty filegroup.
-filegroup {
-    name: "framework-connectivity-tiramisu-sources",
-    srcs: [],
-    visibility: ["//frameworks/base"],
-}
-
-filegroup {
-    name: "framework-connectivity-tiramisu-updatable-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",
-        "//packages/modules/Connectivity:__subpackages__",
-    ],
-}
-
-cc_library_shared {
-    name: "libframework-connectivity-tiramisu-jni",
-    min_sdk_version: "30",
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-unused-parameter",
-        // Don't warn about S API usage even with
-        // min_sdk 30: the library is only loaded
-        // on S+ devices
-        "-Wno-unguarded-availability",
-        "-Wthread-safety",
-    ],
-    srcs: [
-        "jni/android_net_TrafficStats.cpp",
-        "jni/onload.cpp",
-    ],
-    shared_libs: [
-        "libandroid",
-        "liblog",
-        "libnativehelper",
-    ],
-    stl: "none",
-    apex_available: [
-        "com.android.tethering",
-    ],
-}
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl
deleted file mode 100644
index d06ca65..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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;
-
-parcelable NetworkStats;
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl
deleted file mode 100644
index 3d37488..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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;
-
-parcelable NetworkTemplate;
diff --git a/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
deleted file mode 100644
index 657bdd1..0000000
--- a/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.nsd;
-
-@JavaOnlyStableParcelable parcelable NsdServiceInfo;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
deleted file mode 100644
index f3c58b1..0000000
--- a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-#include <android/file_descriptor_jni.h>
-#include <android/multinetwork.h>
-#include <nativehelper/JNIHelp.h>
-
-namespace android {
-
-static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) {
-  int fd = AFileDescriptor_getFd(env, fileDescriptor);
-  if (fd == -1) return -EBADF;
-  return android_tag_socket_with_uid(fd, tag, uid);
-}
-
-static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
-  int fd = AFileDescriptor_getFd(env, fileDescriptor);
-  if (fd == -1) return -EBADF;
-  return android_untag_socket(fd);
-}
-
-static const JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd },
-    { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd },
-};
-
-int register_android_net_TrafficStats(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
-}
-
-};  // namespace android
-
diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp
deleted file mode 100644
index 1fb42c6..0000000
--- a/packages/ConnectivityT/framework-t/jni/onload.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "FrameworkConnectivityJNI"
-
-#include <log/log.h>
-#include <nativehelper/JNIHelp.h>
-
-namespace android {
-
-int register_android_net_TrafficStats(JNIEnv* env);
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
-    JNIEnv *env;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
-        return JNI_ERR;
-    }
-
-    if (register_android_net_TrafficStats(env) < 0) return JNI_ERR;
-
-    return JNI_VERSION_1_6;
-}
-
-};  // namespace android
-
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
deleted file mode 100644
index 2b6570a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ /dev/null
@@ -1,742 +0,0 @@
-/**
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package android.app.usage;
-
-import android.annotation.IntDef;
-import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.TrafficStats;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.net.module.util.CollectionUtils;
-
-import dalvik.system.CloseGuard;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-
-/**
- * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
- * are returned as results to various queries in {@link NetworkStatsManager}.
- */
-public final class NetworkStats implements AutoCloseable {
-    private final static String TAG = "NetworkStats";
-
-    private final CloseGuard mCloseGuard = CloseGuard.get();
-
-    /**
-     * Start timestamp of stats collected
-     */
-    private final long mStartTimeStamp;
-
-    /**
-     * End timestamp of stats collected
-     */
-    private final long mEndTimeStamp;
-
-    /**
-     * Non-null array indicates the query enumerates over uids.
-     */
-    private int[] mUids;
-
-    /**
-     * Index of the current uid in mUids when doing uid enumeration or a single uid value,
-     * depending on query type.
-     */
-    private int mUidOrUidIndex;
-
-    /**
-     * Tag id in case if was specified in the query.
-     */
-    private int mTag = android.net.NetworkStats.TAG_NONE;
-
-    /**
-     * State in case it was not specified in the query.
-     */
-    private int mState = Bucket.STATE_ALL;
-
-    /**
-     * The session while the query requires it, null if all the stats have been collected or close()
-     * has been called.
-     */
-    private INetworkStatsSession mSession;
-    private NetworkTemplate mTemplate;
-
-    /**
-     * Results of a summary query.
-     */
-    private android.net.NetworkStats mSummary = null;
-
-    /**
-     * Results of detail queries.
-     */
-    private NetworkStatsHistory mHistory = null;
-
-    /**
-     * Where we are in enumerating over the current result.
-     */
-    private int mEnumerationIndex = 0;
-
-    /**
-     * Recycling entry objects to prevent heap fragmentation.
-     */
-    private android.net.NetworkStats.Entry mRecycledSummaryEntry = null;
-    private NetworkStatsHistory.Entry mRecycledHistoryEntry = null;
-
-    /** @hide */
-    NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp,
-            long endTimestamp, INetworkStatsService statsService)
-            throws RemoteException, SecurityException {
-        // Open network stats session
-        mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName());
-        mCloseGuard.open("close");
-        mTemplate = template;
-        mStartTimeStamp = startTimestamp;
-        mEndTimeStamp = endTimestamp;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mCloseGuard != null) {
-                mCloseGuard.warnIfOpen();
-            }
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    // -------------------------BEGINNING OF PUBLIC API-----------------------------------
-
-    /**
-     * Buckets are the smallest elements of a query result. As some dimensions of a result may be
-     * aggregated (e.g. time or state) some values may be equal across all buckets.
-     */
-    public static class Bucket {
-        /** @hide */
-        @IntDef(prefix = { "STATE_" }, value = {
-                STATE_ALL,
-                STATE_DEFAULT,
-                STATE_FOREGROUND
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface State {}
-
-        /**
-         * Combined usage across all states.
-         */
-        public static final int STATE_ALL = -1;
-
-        /**
-         * Usage not accounted for in any other state.
-         */
-        public static final int STATE_DEFAULT = 0x1;
-
-        /**
-         * Foreground usage.
-         */
-        public static final int STATE_FOREGROUND = 0x2;
-
-        /**
-         * Special UID value for aggregate/unspecified.
-         */
-        public static final int UID_ALL = android.net.NetworkStats.UID_ALL;
-
-        /**
-         * Special UID value for removed apps.
-         */
-        public static final int UID_REMOVED = TrafficStats.UID_REMOVED;
-
-        /**
-         * Special UID value for data usage by tethering.
-         */
-        public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
-
-        /** @hide */
-        @IntDef(prefix = { "METERED_" }, value = {
-                METERED_ALL,
-                METERED_NO,
-                METERED_YES
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Metered {}
-
-        /**
-         * Combined usage across all metered states. Covers metered and unmetered usage.
-         */
-        public static final int METERED_ALL = -1;
-
-        /**
-         * Usage that occurs on an unmetered network.
-         */
-        public static final int METERED_NO = 0x1;
-
-        /**
-         * Usage that occurs on a metered network.
-         *
-         * <p>A network is classified as metered when the user is sensitive to heavy data usage on
-         * that connection.
-         */
-        public static final int METERED_YES = 0x2;
-
-        /** @hide */
-        @IntDef(prefix = { "ROAMING_" }, value = {
-                ROAMING_ALL,
-                ROAMING_NO,
-                ROAMING_YES
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Roaming {}
-
-        /**
-         * Combined usage across all roaming states. Covers both roaming and non-roaming usage.
-         */
-        public static final int ROAMING_ALL = -1;
-
-        /**
-         * Usage that occurs on a home, non-roaming network.
-         *
-         * <p>Any cellular usage in this bucket was incurred while the device was connected to a
-         * tower owned or operated by the user's wireless carrier, or a tower that the user's
-         * wireless carrier has indicated should be treated as a home network regardless.
-         *
-         * <p>This is also the default value for network types that do not support roaming.
-         */
-        public static final int ROAMING_NO = 0x1;
-
-        /**
-         * Usage that occurs on a roaming network.
-         *
-         * <p>Any cellular usage in this bucket as incurred while the device was roaming on another
-         * carrier's network, for which additional charges may apply.
-         */
-        public static final int ROAMING_YES = 0x2;
-
-        /** @hide */
-        @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = {
-                DEFAULT_NETWORK_ALL,
-                DEFAULT_NETWORK_NO,
-                DEFAULT_NETWORK_YES
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface DefaultNetworkStatus {}
-
-        /**
-         * Combined usage for this network regardless of default network status.
-         */
-        public static final int DEFAULT_NETWORK_ALL = -1;
-
-        /**
-         * Usage that occurs while this network is not a default network.
-         *
-         * <p>This implies that the app responsible for this usage requested that it occur on a
-         * specific network different from the one(s) the system would have selected for it.
-         */
-        public static final int DEFAULT_NETWORK_NO = 0x1;
-
-        /**
-         * Usage that occurs while this network is a default network.
-         *
-         * <p>This implies that the app either did not select a specific network for this usage,
-         * or it selected a network that the system could have selected for app traffic.
-         */
-        public static final int DEFAULT_NETWORK_YES = 0x2;
-
-        /**
-         * Special TAG value for total data across all tags
-         */
-        public static final int TAG_NONE = android.net.NetworkStats.TAG_NONE;
-
-        private int mUid;
-        private int mTag;
-        private int mState;
-        private int mDefaultNetworkStatus;
-        private int mMetered;
-        private int mRoaming;
-        private long mBeginTimeStamp;
-        private long mEndTimeStamp;
-        private long mRxBytes;
-        private long mRxPackets;
-        private long mTxBytes;
-        private long mTxPackets;
-
-        private static int convertSet(@State int state) {
-            switch (state) {
-                case STATE_ALL: return android.net.NetworkStats.SET_ALL;
-                case STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT;
-                case STATE_FOREGROUND: return android.net.NetworkStats.SET_FOREGROUND;
-            }
-            return 0;
-        }
-
-        private static @State int convertState(int networkStatsSet) {
-            switch (networkStatsSet) {
-                case android.net.NetworkStats.SET_ALL : return STATE_ALL;
-                case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
-                case android.net.NetworkStats.SET_FOREGROUND : return STATE_FOREGROUND;
-            }
-            return 0;
-        }
-
-        private static int convertUid(int uid) {
-            switch (uid) {
-                case TrafficStats.UID_REMOVED: return UID_REMOVED;
-                case TrafficStats.UID_TETHERING: return UID_TETHERING;
-            }
-            return uid;
-        }
-
-        private static int convertTag(int tag) {
-            switch (tag) {
-                case android.net.NetworkStats.TAG_NONE: return TAG_NONE;
-            }
-            return tag;
-        }
-
-        private static @Metered int convertMetered(int metered) {
-            switch (metered) {
-                case android.net.NetworkStats.METERED_ALL : return METERED_ALL;
-                case android.net.NetworkStats.METERED_NO: return METERED_NO;
-                case android.net.NetworkStats.METERED_YES: return METERED_YES;
-            }
-            return 0;
-        }
-
-        private static @Roaming int convertRoaming(int roaming) {
-            switch (roaming) {
-                case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
-                case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO;
-                case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES;
-            }
-            return 0;
-        }
-
-        private static @DefaultNetworkStatus int convertDefaultNetworkStatus(
-                int defaultNetworkStatus) {
-            switch (defaultNetworkStatus) {
-                case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL;
-                case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO;
-                case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES;
-            }
-            return 0;
-        }
-
-        public Bucket() {
-        }
-
-        /**
-         * Key of the bucket. Usually an app uid or one of the following special values:<p />
-         * <ul>
-         * <li>{@link #UID_REMOVED}</li>
-         * <li>{@link #UID_TETHERING}</li>
-         * <li>{@link android.os.Process#SYSTEM_UID}</li>
-         * </ul>
-         * @return Bucket key.
-         */
-        public int getUid() {
-            return mUid;
-        }
-
-        /**
-         * Tag of the bucket.<p />
-         * @return Bucket tag.
-         */
-        public int getTag() {
-            return mTag;
-        }
-
-        /**
-         * Usage state. One of the following values:<p/>
-         * <ul>
-         * <li>{@link #STATE_ALL}</li>
-         * <li>{@link #STATE_DEFAULT}</li>
-         * <li>{@link #STATE_FOREGROUND}</li>
-         * </ul>
-         * @return Usage state.
-         */
-        public @State int getState() {
-            return mState;
-        }
-
-        /**
-         * Metered state. One of the following values:<p/>
-         * <ul>
-         * <li>{@link #METERED_ALL}</li>
-         * <li>{@link #METERED_NO}</li>
-         * <li>{@link #METERED_YES}</li>
-         * </ul>
-         * <p>A network is classified as metered when the user is sensitive to heavy data usage on
-         * that connection. Apps may warn before using these networks for large downloads. The
-         * metered state can be set by the user within data usage network restrictions.
-         */
-        public @Metered int getMetered() {
-            return mMetered;
-        }
-
-        /**
-         * Roaming state. One of the following values:<p/>
-         * <ul>
-         * <li>{@link #ROAMING_ALL}</li>
-         * <li>{@link #ROAMING_NO}</li>
-         * <li>{@link #ROAMING_YES}</li>
-         * </ul>
-         */
-        public @Roaming int getRoaming() {
-            return mRoaming;
-        }
-
-        /**
-         * Default network status. One of the following values:<p/>
-         * <ul>
-         * <li>{@link #DEFAULT_NETWORK_ALL}</li>
-         * <li>{@link #DEFAULT_NETWORK_NO}</li>
-         * <li>{@link #DEFAULT_NETWORK_YES}</li>
-         * </ul>
-         */
-        public @DefaultNetworkStatus int getDefaultNetworkStatus() {
-            return mDefaultNetworkStatus;
-        }
-
-        /**
-         * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see
-         * {@link java.lang.System#currentTimeMillis}.
-         * @return Start of interval.
-         */
-        public long getStartTimeStamp() {
-            return mBeginTimeStamp;
-        }
-
-        /**
-         * End timestamp of the bucket's time interval. Defined in terms of "Unix time", see
-         * {@link java.lang.System#currentTimeMillis}.
-         * @return End of interval.
-         */
-        public long getEndTimeStamp() {
-            return mEndTimeStamp;
-        }
-
-        /**
-         * Number of bytes received during the bucket's time interval. Statistics are measured at
-         * the network layer, so they include both TCP and UDP usage.
-         * @return Number of bytes.
-         */
-        public long getRxBytes() {
-            return mRxBytes;
-        }
-
-        /**
-         * Number of bytes transmitted during the bucket's time interval. Statistics are measured at
-         * the network layer, so they include both TCP and UDP usage.
-         * @return Number of bytes.
-         */
-        public long getTxBytes() {
-            return mTxBytes;
-        }
-
-        /**
-         * Number of packets received during the bucket's time interval. Statistics are measured at
-         * the network layer, so they include both TCP and UDP usage.
-         * @return Number of packets.
-         */
-        public long getRxPackets() {
-            return mRxPackets;
-        }
-
-        /**
-         * Number of packets transmitted during the bucket's time interval. Statistics are measured
-         * at the network layer, so they include both TCP and UDP usage.
-         * @return Number of packets.
-         */
-        public long getTxPackets() {
-            return mTxPackets;
-        }
-    }
-
-    /**
-     * Fills the recycled bucket with data of the next bin in the enumeration.
-     * @param bucketOut Bucket to be filled with data.
-     * @return true if successfully filled the bucket, false otherwise.
-     */
-    public boolean getNextBucket(Bucket bucketOut) {
-        if (mSummary != null) {
-            return getNextSummaryBucket(bucketOut);
-        } else {
-            return getNextHistoryBucket(bucketOut);
-        }
-    }
-
-    /**
-     * Check if it is possible to ask for a next bucket in the enumeration.
-     * @return true if there is at least one more bucket.
-     */
-    public boolean hasNextBucket() {
-        if (mSummary != null) {
-            return mEnumerationIndex < mSummary.size();
-        } else if (mHistory != null) {
-            return mEnumerationIndex < mHistory.size()
-                    || hasNextUid();
-        }
-        return false;
-    }
-
-    /**
-     * Closes the enumeration. Call this method before this object gets out of scope.
-     */
-    @Override
-    public void close() {
-        if (mSession != null) {
-            try {
-                mSession.close();
-            } catch (RemoteException e) {
-                Log.w(TAG, e);
-                // Otherwise, meh
-            }
-        }
-        mSession = null;
-        if (mCloseGuard != null) {
-            mCloseGuard.close();
-        }
-    }
-
-    // -------------------------END OF PUBLIC API-----------------------------------
-
-    /**
-     * Collects device summary results into a Bucket.
-     * @throws RemoteException
-     */
-    Bucket getDeviceSummaryForNetwork() throws RemoteException {
-        mSummary = mSession.getDeviceSummaryForNetwork(mTemplate, mStartTimeStamp, mEndTimeStamp);
-
-        // Setting enumeration index beyond end to avoid accidental enumeration over data that does
-        // not belong to the calling user.
-        mEnumerationIndex = mSummary.size();
-
-        return getSummaryAggregate();
-    }
-
-    /**
-     * Collects summary results and sets summary enumeration mode.
-     * @throws RemoteException
-     */
-    void startSummaryEnumeration() throws RemoteException {
-        mSummary = mSession.getSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp,
-                false /* includeTags */);
-        mEnumerationIndex = 0;
-    }
-
-    /**
-     * Collects tagged summary results and sets summary enumeration mode.
-     * @throws RemoteException
-     */
-    void startTaggedSummaryEnumeration() throws RemoteException {
-        mSummary = mSession.getTaggedSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp);
-        mEnumerationIndex = 0;
-    }
-
-    /**
-     * Collects history results for uid and resets history enumeration index.
-     */
-    void startHistoryUidEnumeration(int uid, int tag, int state) {
-        mHistory = null;
-        try {
-            mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
-                    Bucket.convertSet(state), tag, NetworkStatsHistory.FIELD_ALL,
-                    mStartTimeStamp, mEndTimeStamp);
-            setSingleUidTagState(uid, tag, state);
-        } catch (RemoteException e) {
-            Log.w(TAG, e);
-            // Leaving mHistory null
-        }
-        mEnumerationIndex = 0;
-    }
-
-    /**
-     * Collects history results for network and resets history enumeration index.
-     */
-    void startHistoryDeviceEnumeration() {
-        try {
-            mHistory = mSession.getHistoryIntervalForNetwork(
-                    mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
-        } catch (RemoteException e) {
-            Log.w(TAG, e);
-            mHistory = null;
-        }
-        mEnumerationIndex = 0;
-    }
-
-    /**
-     * Starts uid enumeration for current user.
-     * @throws RemoteException
-     */
-    void startUserUidEnumeration() throws RemoteException {
-        // TODO: getRelevantUids should be sensitive to time interval. When that's done,
-        //       the filtering logic below can be removed.
-        int[] uids = mSession.getRelevantUids();
-        // Filtering of uids with empty history.
-        final ArrayList<Integer> filteredUids = new ArrayList<>();
-        for (int uid : uids) {
-            try {
-                NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid,
-                        android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
-                        NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
-                if (history != null && history.size() > 0) {
-                    filteredUids.add(uid);
-                }
-            } catch (RemoteException e) {
-                Log.w(TAG, "Error while getting history of uid " + uid, e);
-            }
-        }
-        mUids = CollectionUtils.toIntArray(filteredUids);
-        mUidOrUidIndex = -1;
-        stepHistory();
-    }
-
-    /**
-     * Steps to next uid in enumeration and collects history for that.
-     */
-    private void stepHistory(){
-        if (hasNextUid()) {
-            stepUid();
-            mHistory = null;
-            try {
-                mHistory = mSession.getHistoryIntervalForUid(mTemplate, getUid(),
-                        android.net.NetworkStats.SET_ALL, android.net.NetworkStats.TAG_NONE,
-                        NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
-            } catch (RemoteException e) {
-                Log.w(TAG, e);
-                // Leaving mHistory null
-            }
-            mEnumerationIndex = 0;
-        }
-    }
-
-    private void fillBucketFromSummaryEntry(Bucket bucketOut) {
-        bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid);
-        bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag);
-        bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set);
-        bucketOut.mDefaultNetworkStatus = Bucket.convertDefaultNetworkStatus(
-                mRecycledSummaryEntry.defaultNetwork);
-        bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered);
-        bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming);
-        bucketOut.mBeginTimeStamp = mStartTimeStamp;
-        bucketOut.mEndTimeStamp = mEndTimeStamp;
-        bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes;
-        bucketOut.mRxPackets = mRecycledSummaryEntry.rxPackets;
-        bucketOut.mTxBytes = mRecycledSummaryEntry.txBytes;
-        bucketOut.mTxPackets = mRecycledSummaryEntry.txPackets;
-    }
-
-    /**
-     * Getting the next item in summary enumeration.
-     * @param bucketOut Next item will be set here.
-     * @return true if a next item could be set.
-     */
-    private boolean getNextSummaryBucket(Bucket bucketOut) {
-        if (bucketOut != null && mEnumerationIndex < mSummary.size()) {
-            mRecycledSummaryEntry = mSummary.getValues(mEnumerationIndex++, mRecycledSummaryEntry);
-            fillBucketFromSummaryEntry(bucketOut);
-            return true;
-        }
-        return false;
-    }
-
-    Bucket getSummaryAggregate() {
-        if (mSummary == null) {
-            return null;
-        }
-        Bucket bucket = new Bucket();
-        if (mRecycledSummaryEntry == null) {
-            mRecycledSummaryEntry = new android.net.NetworkStats.Entry();
-        }
-        mSummary.getTotal(mRecycledSummaryEntry);
-        fillBucketFromSummaryEntry(bucket);
-        return bucket;
-    }
-
-    /**
-     * Getting the next item in a history enumeration.
-     * @param bucketOut Next item will be set here.
-     * @return true if a next item could be set.
-     */
-    private boolean getNextHistoryBucket(Bucket bucketOut) {
-        if (bucketOut != null && mHistory != null) {
-            if (mEnumerationIndex < mHistory.size()) {
-                mRecycledHistoryEntry = mHistory.getValues(mEnumerationIndex++,
-                        mRecycledHistoryEntry);
-                bucketOut.mUid = Bucket.convertUid(getUid());
-                bucketOut.mTag = Bucket.convertTag(mTag);
-                bucketOut.mState = mState;
-                bucketOut.mDefaultNetworkStatus = Bucket.DEFAULT_NETWORK_ALL;
-                bucketOut.mMetered = Bucket.METERED_ALL;
-                bucketOut.mRoaming = Bucket.ROAMING_ALL;
-                bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart;
-                bucketOut.mEndTimeStamp = mRecycledHistoryEntry.bucketStart +
-                        mRecycledHistoryEntry.bucketDuration;
-                bucketOut.mRxBytes = mRecycledHistoryEntry.rxBytes;
-                bucketOut.mRxPackets = mRecycledHistoryEntry.rxPackets;
-                bucketOut.mTxBytes = mRecycledHistoryEntry.txBytes;
-                bucketOut.mTxPackets = mRecycledHistoryEntry.txPackets;
-                return true;
-            } else if (hasNextUid()) {
-                stepHistory();
-                return getNextHistoryBucket(bucketOut);
-            }
-        }
-        return false;
-    }
-
-    // ------------------ UID LOGIC------------------------
-
-    private boolean isUidEnumeration() {
-        return mUids != null;
-    }
-
-    private boolean hasNextUid() {
-        return isUidEnumeration() && (mUidOrUidIndex + 1) < mUids.length;
-    }
-
-    private int getUid() {
-        // Check if uid enumeration.
-        if (isUidEnumeration()) {
-            if (mUidOrUidIndex < 0 || mUidOrUidIndex >= mUids.length) {
-                throw new IndexOutOfBoundsException(
-                        "Index=" + mUidOrUidIndex + " mUids.length=" + mUids.length);
-            }
-            return mUids[mUidOrUidIndex];
-        }
-        // Single uid mode.
-        return mUidOrUidIndex;
-    }
-
-    private void setSingleUidTagState(int uid, int tag, int state) {
-        mUidOrUidIndex = uid;
-        mTag = tag;
-        mState = state;
-    }
-
-    private void stepUid() {
-        if (mUids != null) {
-            ++mUidOrUidIndex;
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
deleted file mode 100644
index bf518b2..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ /dev/null
@@ -1,1181 +0,0 @@
-/**
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package android.app.usage;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.annotation.WorkerThread;
-import android.app.usage.NetworkStats.Bucket;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.DataUsageRequest;
-import android.net.INetworkStatsService;
-import android.net.Network;
-import android.net.NetworkStack;
-import android.net.NetworkStateSnapshot;
-import android.net.NetworkTemplate;
-import android.net.UnderlyingNetworkInfo;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.NetworkStatsDataMigrationUtils;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Build;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Provides access to network usage history and statistics. Usage data is collected in
- * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
- * <p />
- * Queries can define a time interval in the form of start and end timestamps (Long.MIN_VALUE and
- * Long.MAX_VALUE can be used to simulate open ended intervals). By default, apps can only obtain
- * data about themselves. See the below note for special cases in which apps can obtain data about
- * other applications.
- * <h3>
- * Summary queries
- * </h3>
- * {@link #querySummaryForDevice} <p />
- * {@link #querySummaryForUser} <p />
- * {@link #querySummary} <p />
- * These queries aggregate network usage across the whole interval. Therefore there will be only one
- * bucket for a particular key, state, metered and roaming combination. In case of the user-wide
- * and device-wide summaries a single bucket containing the totalised network usage is returned.
- * <h3>
- * History queries
- * </h3>
- * {@link #queryDetailsForUid} <p />
- * {@link #queryDetails} <p />
- * These queries do not aggregate over time but do aggregate over state, metered and roaming.
- * Therefore there can be multiple buckets for a particular key. However, all Buckets will have
- * {@code state} {@link NetworkStats.Bucket#STATE_ALL},
- * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
- * {@code metered } {@link NetworkStats.Bucket#METERED_ALL},
- * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}.
- * <p />
- * <b>NOTE:</b> Calling {@link #querySummaryForDevice} or accessing stats for apps other than the
- * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS},
- * which is a system-level permission and will not be granted to third-party apps. However,
- * declaring the permission implies intention to use the API and the user of the device can grant
- * permission through the Settings application.
- * <p />
- * Profile owner apps are automatically granted permission to query data on the profile they manage
- * (that is, for any query except {@link #querySummaryForDevice}). Device owner apps and carrier-
- * privileged apps likewise get access to usage data for all users on the device.
- * <p />
- * In addition to tethering usage, usage by removed users and apps, and usage by the system
- * is also included in the results for callers with one of these higher levels of access.
- * <p />
- * <b>NOTE:</b> Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required
- * the above permission, even to access an app's own data usage, and carrier-privileged apps were
- * not included.
- */
-@SystemService(Context.NETWORK_STATS_SERVICE)
-public class NetworkStatsManager {
-    private static final String TAG = "NetworkStatsManager";
-    private static final boolean DBG = false;
-
-    /** @hide */
-    public static final int CALLBACK_LIMIT_REACHED = 0;
-    /** @hide */
-    public static final int CALLBACK_RELEASED = 1;
-
-    /**
-     * Minimum data usage threshold for registering usage callbacks.
-     *
-     * Requests registered with a threshold lower than this will only be triggered once this minimum
-     * is reached.
-     * @hide
-     */
-    public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
-
-    private final Context mContext;
-    private final INetworkStatsService mService;
-
-    /**
-     * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT}
-     * instead.
-     * @hide
-     */
-    @Deprecated
-    public static final String PREFIX_DEV = "dev";
-
-    /** @hide */
-    public static final int FLAG_POLL_ON_OPEN = 1 << 0;
-    /** @hide */
-    public static final int FLAG_POLL_FORCE = 1 << 1;
-    /** @hide */
-    public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
-
-    /**
-     * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
-     * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
-     * with NR state as connected. This is a concept added by NetworkStats on top of the telephony
-     * constants for backward compatibility of metrics so this should not be overlapped with any of
-     * the {@code TelephonyManager.NETWORK_TYPE_*} constants.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int NETWORK_TYPE_5G_NSA = -2;
-
-    private int mFlags;
-
-    /** @hide */
-    @VisibleForTesting
-    public NetworkStatsManager(Context context, INetworkStatsService service) {
-        mContext = context;
-        mService = service;
-        setPollOnOpen(true);
-        setAugmentWithSubscriptionPlan(true);
-    }
-
-    /** @hide */
-    public INetworkStatsService getBinder() {
-        return mService;
-    }
-
-    /**
-     * Set poll on open flag to indicate the poll is needed before service gets statistics
-     * result. This is default enabled. However, for any non-privileged caller, the poll might
-     * be omitted in case of rate limiting.
-     *
-     * @param pollOnOpen true if poll is needed.
-     * @hide
-     */
-    // The system will ignore any non-default values for non-privileged
-    // processes, so processes that don't hold the appropriate permissions
-    // can make no use of this API.
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    public void setPollOnOpen(boolean pollOnOpen) {
-        if (pollOnOpen) {
-            mFlags |= FLAG_POLL_ON_OPEN;
-        } else {
-            mFlags &= ~FLAG_POLL_ON_OPEN;
-        }
-    }
-
-    /**
-     * Set poll force flag to indicate that calling any subsequent query method will force a stats
-     * poll.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void setPollForce(boolean pollForce) {
-        if (pollForce) {
-            mFlags |= FLAG_POLL_FORCE;
-        } else {
-            mFlags &= ~FLAG_POLL_FORCE;
-        }
-    }
-
-    /** @hide */
-    public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) {
-        if (augmentWithSubscriptionPlan) {
-            mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
-        } else {
-            mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
-        }
-    }
-
-    /**
-     * Query network usage statistics summaries.
-     *
-     * Result is summarised data usage for the whole
-     * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
-     * roaming. This means the bucket's start and end timestamp will be the same as the
-     * 'startTime' and 'endTime' arguments. State is going to be
-     * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
-     * tag {@link NetworkStats.Bucket#TAG_NONE},
-     * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
-     * metered {@link NetworkStats.Bucket#METERED_ALL},
-     * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param startTime Start of period, in milliseconds since the Unix epoch, see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period, in milliseconds since the Unix epoch, see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Bucket Summarised data usage.
-     *
-     * @hide
-     */
-    @NonNull
-    @WorkerThread
-    @SystemApi(client = MODULE_LIBRARIES)
-    public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
-            long startTime, long endTime) {
-        Objects.requireNonNull(template);
-        try {
-            NetworkStats stats =
-                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-            Bucket bucket = stats.getDeviceSummaryForNetwork();
-            stats.close();
-            return bucket;
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return null; // To make the compiler happy.
-    }
-
-    /**
-     * Query network usage statistics summaries. Result is summarised data usage for the whole
-     * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and
-     * roaming. This means the bucket's start and end timestamp are going to be the same as the
-     * 'startTime' and 'endTime' parameters. State is going to be
-     * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL},
-     * tag {@link NetworkStats.Bucket#TAG_NONE},
-     * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
-     * metered {@link NetworkStats.Bucket#METERED_ALL},
-     * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param networkType As defined in {@link ConnectivityManager}, e.g.
-     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
-     *            etc.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when querying for the mobile network type to receive usage
-     *                     for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param startTime Start of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Bucket object or null if permissions are insufficient or error happened during
-     *         statistics collection.
-     */
-    @WorkerThread
-    public Bucket querySummaryForDevice(int networkType, String subscriberId,
-            long startTime, long endTime) throws SecurityException, RemoteException {
-        NetworkTemplate template;
-        try {
-            template = createTemplate(networkType, subscriberId);
-        } catch (IllegalArgumentException e) {
-            if (DBG) Log.e(TAG, "Cannot create template", e);
-            return null;
-        }
-
-        return querySummaryForDevice(template, startTime, endTime);
-    }
-
-    /**
-     * Query network usage statistics summaries. Result is summarised data usage for all uids
-     * belonging to calling user. Result is a single Bucket aggregated over time, state and uid.
-     * This means the bucket's start and end timestamp are going to be the same as the 'startTime'
-     * and 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL},
-     * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE},
-     * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming
-     * {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param networkType As defined in {@link ConnectivityManager}, e.g.
-     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
-     *            etc.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when querying for the mobile network type to receive usage
-     *                     for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param startTime Start of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Bucket object or null if permissions are insufficient or error happened during
-     *         statistics collection.
-     */
-    @WorkerThread
-    public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime,
-            long endTime) throws SecurityException, RemoteException {
-        NetworkTemplate template;
-        try {
-            template = createTemplate(networkType, subscriberId);
-        } catch (IllegalArgumentException e) {
-            if (DBG) Log.e(TAG, "Cannot create template", e);
-            return null;
-        }
-
-        NetworkStats stats;
-        stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-        stats.startSummaryEnumeration();
-
-        stats.close();
-        return stats.getSummaryAggregate();
-    }
-
-    /**
-     * Query network usage statistics summaries. Result filtered to include only uids belonging to
-     * calling user. Result is aggregated over time, hence all buckets will have the same start and
-     * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This
-     * means buckets' start and end timestamps are going to be the same as the 'startTime' and
-     * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to
-     * be the same.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param networkType As defined in {@link ConnectivityManager}, e.g.
-     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
-     *            etc.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when querying for the mobile network type to receive usage
-     *                     for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param startTime Start of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Statistics object or null if permissions are insufficient or error happened during
-     *         statistics collection.
-     */
-    @WorkerThread
-    public NetworkStats querySummary(int networkType, String subscriberId, long startTime,
-            long endTime) throws SecurityException, RemoteException {
-        NetworkTemplate template;
-        try {
-            template = createTemplate(networkType, subscriberId);
-        } catch (IllegalArgumentException e) {
-            if (DBG) Log.e(TAG, "Cannot create template", e);
-            return null;
-        }
-
-        return querySummary(template, startTime, endTime);
-    }
-
-    /**
-     * Query network usage statistics summaries.
-     *
-     * The results will only include traffic made by UIDs belonging to the calling user profile.
-     * The results are aggregated over time, so that all buckets will have the same start and
-     * end timestamps as the passed arguments. Not aggregated over state, uid, default network,
-     * metered, or roaming.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param startTime Start of period, in milliseconds since the Unix epoch, see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period, in milliseconds since the Unix epoch, see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Statistics which is described above.
-     * @hide
-     */
-    @NonNull
-    @SystemApi(client = MODULE_LIBRARIES)
-    @WorkerThread
-    public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
-            long endTime) throws SecurityException {
-        Objects.requireNonNull(template);
-        try {
-            NetworkStats result =
-                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-            result.startSummaryEnumeration();
-            return result;
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return null; // To make the compiler happy.
-    }
-
-    /**
-     * Query tagged network usage statistics summaries.
-     *
-     * The results will only include tagged traffic made by UIDs belonging to the calling user
-     * profile. The results are aggregated over time, so that all buckets will have the same
-     * start and end timestamps as the passed arguments. Not aggregated over state, uid,
-     * default network, metered, or roaming.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param startTime Start of period, in milliseconds since the Unix epoch, see
-     *            {@link System#currentTimeMillis}.
-     * @param endTime End of period, in milliseconds since the Unix epoch, see
-     *            {@link System#currentTimeMillis}.
-     * @return Statistics which is described above.
-     * @hide
-     */
-    @NonNull
-    @SystemApi(client = MODULE_LIBRARIES)
-    @WorkerThread
-    public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
-            long endTime) throws SecurityException {
-        Objects.requireNonNull(template);
-        try {
-            NetworkStats result =
-                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-            result.startTaggedSummaryEnumeration();
-            return result;
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        return null; // To make the compiler happy.
-    }
-
-    /**
-     * Query usage statistics details for networks matching a given {@link NetworkTemplate}.
-     *
-     * Result is not aggregated over time. This means buckets' start and
-     * end timestamps will be between 'startTime' and 'endTime' parameters.
-     * <p>Only includes buckets whose entire time period is included between
-     * startTime and endTime. Doesn't interpolate or return partial buckets.
-     * Since bucket length is in the order of hours, this
-     * method cannot be used to measure data usage on a fine grained time scale.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param startTime Start of period, in milliseconds since the Unix epoch, see
-     *                  {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period, in milliseconds since the Unix epoch, see
-     *                {@link java.lang.System#currentTimeMillis}.
-     * @return Statistics which is described above.
-     * @hide
-     */
-    @NonNull
-    @SystemApi(client = MODULE_LIBRARIES)
-    @WorkerThread
-    public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
-            long startTime, long endTime) {
-        Objects.requireNonNull(template);
-        try {
-            final NetworkStats result =
-                    new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-            result.startHistoryDeviceEnumeration();
-            return result;
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-
-        return null; // To make the compiler happy.
-    }
-
-    /**
-     * Query network usage statistics details for a given uid.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
-     */
-    @WorkerThread
-    public NetworkStats queryDetailsForUid(int networkType, String subscriberId,
-            long startTime, long endTime, int uid) throws SecurityException {
-        return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
-            NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
-    }
-
-    /** @hide */
-    public NetworkStats queryDetailsForUid(NetworkTemplate template,
-            long startTime, long endTime, int uid) throws SecurityException {
-        return queryDetailsForUidTagState(template, startTime, endTime, uid,
-                NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
-    }
-
-    /**
-     * Query network usage statistics details for a given uid and tag.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int)
-     */
-    @WorkerThread
-    public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId,
-            long startTime, long endTime, int uid, int tag) throws SecurityException {
-        return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid,
-            tag, NetworkStats.Bucket.STATE_ALL);
-    }
-
-    /**
-     * Query network usage statistics details for a given uid, tag, and state. Only usable for uids
-     * belonging to calling user. Result is not aggregated over time. This means buckets' start and
-     * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going
-     * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state
-     * the same as the 'state' parameter.
-     * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
-     * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
-     * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
-     * interpolate across partial buckets. Since bucket length is in the order of hours, this
-     * method cannot be used to measure data usage on a fine grained time scale.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param networkType As defined in {@link ConnectivityManager}, e.g.
-     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
-     *            etc.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when querying for the mobile network type to receive usage
-     *                     for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param startTime Start of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param uid UID of app
-     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
-     *            across all the tags.
-     * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
-     *            traffic from all states.
-     * @return Statistics object or null if an error happened during statistics collection.
-     * @throws SecurityException if permissions are insufficient to read network statistics.
-     */
-    @WorkerThread
-    public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId,
-            long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
-        NetworkTemplate template;
-        template = createTemplate(networkType, subscriberId);
-
-        return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
-    }
-
-    /**
-     * Query network usage statistics details for a given template, uid, tag, and state.
-     *
-     * Only usable for uids belonging to calling user. Result is not aggregated over time.
-     * This means buckets' start and end timestamps are going to be between 'startTime' and
-     * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
-     * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
-     * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
-     * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
-     * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
-     * interpolate across partial buckets. Since bucket length is in the order of hours, this
-     * method cannot be used to measure data usage on a fine grained time scale.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param startTime Start of period, in milliseconds since the Unix epoch, see
-     *                  {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period, in milliseconds since the Unix epoch, see
-     *                {@link java.lang.System#currentTimeMillis}.
-     * @param uid UID of app
-     * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
-     *            across all the tags.
-     * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
-     *            traffic from all states.
-     * @return Statistics which is described above.
-     * @hide
-     */
-    @NonNull
-    @SystemApi(client = MODULE_LIBRARIES)
-    @WorkerThread
-    public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
-            long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
-        Objects.requireNonNull(template);
-        try {
-            final NetworkStats result = new NetworkStats(
-                    mContext, template, mFlags, startTime, endTime, mService);
-            result.startHistoryUidEnumeration(uid, tag, state);
-            return result;
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
-                    + " state=" + state, e);
-            e.rethrowFromSystemServer();
-        }
-
-        return null; // To make the compiler happy.
-    }
-
-    /**
-     * Query network usage statistics details. Result filtered to include only uids belonging to
-     * calling user. Result is aggregated over state but not aggregated over time, uid, tag,
-     * metered, nor roaming. This means buckets' start and end timestamps are going to be between
-     * 'startTime' and 'endTime' parameters. State is going to be
-     * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary,
-     * tag {@link NetworkStats.Bucket#TAG_NONE},
-     * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
-     * metered is going to be {@link NetworkStats.Bucket#METERED_ALL},
-     * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
-     * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
-     * interpolate across partial buckets. Since bucket length is in the order of hours, this
-     * method cannot be used to measure data usage on a fine grained time scale.
-     * This may take a long time, and apps should avoid calling this on their main thread.
-     *
-     * @param networkType As defined in {@link ConnectivityManager}, e.g.
-     *            {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI}
-     *            etc.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when querying for the mobile network type to receive usage
-     *                     for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param startTime Start of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @param endTime End of period. Defined in terms of "Unix time", see
-     *            {@link java.lang.System#currentTimeMillis}.
-     * @return Statistics object or null if permissions are insufficient or error happened during
-     *         statistics collection.
-     */
-    @WorkerThread
-    public NetworkStats queryDetails(int networkType, String subscriberId, long startTime,
-            long endTime) throws SecurityException, RemoteException {
-        NetworkTemplate template;
-        try {
-            template = createTemplate(networkType, subscriberId);
-        } catch (IllegalArgumentException e) {
-            if (DBG) Log.e(TAG, "Cannot create template", e);
-            return null;
-        }
-
-        NetworkStats result;
-        result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
-        result.startUserUidEnumeration();
-        return result;
-    }
-
-    /**
-     * Query realtime mobile network usage statistics.
-     *
-     * Return a snapshot of current UID network statistics, as it applies
-     * to the mobile radios of the device. The snapshot will include any
-     * tethering traffic, video calling data usage and count of
-     * network operations set by {@link TrafficStats#incrementOperationCount}
-     * made over a mobile radio.
-     * The snapshot will not include any statistics that cannot be seen by
-     * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    @NonNull public android.net.NetworkStats getMobileUidStats() {
-        try {
-            return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
-        } catch (RemoteException e) {
-            if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats");
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Query realtime Wi-Fi network usage statistics.
-     *
-     * Return a snapshot of current UID network statistics, as it applies
-     * to the Wi-Fi radios of the device. The snapshot will include any
-     * tethering traffic, video calling data usage and count of
-     * network operations set by {@link TrafficStats#incrementOperationCount}
-     * made over a Wi-Fi radio.
-     * The snapshot will not include any statistics that cannot be seen by
-     * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    @NonNull public android.net.NetworkStats getWifiUidStats() {
-        try {
-            return mService.getUidStatsForTransport(TRANSPORT_WIFI);
-        } catch (RemoteException e) {
-            if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats");
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Registers to receive notifications about data usage on specified networks.
-     *
-     * <p>The callbacks will continue to be called as long as the process is alive or
-     * {@link #unregisterUsageCallback} is called.
-     *
-     * @param template Template used to match networks. See {@link NetworkTemplate}.
-     * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB
-     *                       will be clamped for callers except callers with the NETWORK_STACK
-     *                       permission.
-     * @param executor The executor on which callback will be invoked. The provided {@link Executor}
-     *                 must run callback sequentially, otherwise the order of callbacks cannot be
-     *                 guaranteed.
-     * @param callback The {@link UsageCallback} that the system will call when data usage
-     *                 has exceeded the specified threshold.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK}, conditional = true)
-    public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
-            @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
-        Objects.requireNonNull(template, "NetworkTemplate cannot be null");
-        Objects.requireNonNull(callback, "UsageCallback cannot be null");
-        Objects.requireNonNull(executor, "Executor cannot be null");
-
-        final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
-                template, thresholdBytes);
-        try {
-            final UsageCallbackWrapper callbackWrapper =
-                    new UsageCallbackWrapper(executor, callback);
-            callback.request = mService.registerUsageCallback(
-                    mContext.getOpPackageName(), request, callbackWrapper);
-            if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
-
-            if (callback.request == null) {
-                Log.e(TAG, "Request from callback is null; should not happen");
-            }
-        } catch (RemoteException e) {
-            if (DBG) Log.d(TAG, "Remote exception when registering callback");
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Registers to receive notifications about data usage on specified networks.
-     *
-     * @see #registerUsageCallback(int, String, long, UsageCallback, Handler)
-     */
-    public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
-            UsageCallback callback) {
-        registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
-                null /* handler */);
-    }
-
-    /**
-     * Registers to receive notifications about data usage on specified networks.
-     *
-     * <p>The callbacks will continue to be called as long as the process is live or
-     * {@link #unregisterUsageCallback} is called.
-     *
-     * @param networkType Type of network to monitor. Either
-                  {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}.
-     * @param subscriberId If applicable, the subscriber id of the network interface.
-     *                     <p>Starting with API level 29, the {@code subscriberId} is guarded by
-     *                     additional restrictions. Calling apps that do not meet the new
-     *                     requirements to access the {@code subscriberId} can provide a {@code
-     *                     null} value when registering for the mobile network type to receive
-     *                     notifications for all mobile networks. For additional details see {@link
-     *                     TelephonyManager#getSubscriberId()}.
-     *                     <p>Starting with API level 31, calling apps can provide a
-     *                     {@code subscriberId} with wifi network type to receive usage for
-     *                     wifi networks which is under the given subscription if applicable.
-     *                     Otherwise, pass {@code null} when querying all wifi networks.
-     * @param thresholdBytes Threshold in bytes to be notified on.
-     * @param callback The {@link UsageCallback} that the system will call when data usage
-     *            has exceeded the specified threshold.
-     * @param handler to dispatch callback events through, otherwise if {@code null} it uses
-     *            the calling thread.
-     */
-    public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
-            UsageCallback callback, @Nullable Handler handler) {
-        NetworkTemplate template = createTemplate(networkType, subscriberId);
-        if (DBG) {
-            Log.d(TAG, "registerUsageCallback called with: {"
-                    + " networkType=" + networkType
-                    + " subscriberId=" + subscriberId
-                    + " thresholdBytes=" + thresholdBytes
-                    + " }");
-        }
-
-        final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r);
-
-        registerUsageCallback(template, thresholdBytes, executor, callback);
-    }
-
-    /**
-     * Unregisters callbacks on data usage.
-     *
-     * @param callback The {@link UsageCallback} used when registering.
-     */
-    public void unregisterUsageCallback(UsageCallback callback) {
-        if (callback == null || callback.request == null
-                || callback.request.requestId == DataUsageRequest.REQUEST_ID_UNSET) {
-            throw new IllegalArgumentException("Invalid UsageCallback");
-        }
-        try {
-            mService.unregisterUsageRequest(callback.request);
-        } catch (RemoteException e) {
-            if (DBG) Log.d(TAG, "Remote exception when unregistering callback");
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Base class for usage callbacks. Should be extended by applications wanting notifications.
-     */
-    public static abstract class UsageCallback {
-        /**
-         * Called when data usage has reached the given threshold.
-         *
-         * Called by {@code NetworkStatsService} when the registered threshold is reached.
-         * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system
-         * will not call {@link #onThresholdReached(int, String)}.
-         *
-         * @param template The {@link NetworkTemplate} that associated with this callback.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public void onThresholdReached(@NonNull NetworkTemplate template) {
-            // Backward compatibility for those who didn't override this function.
-            final int networkType = networkTypeForTemplate(template);
-            if (networkType != ConnectivityManager.TYPE_NONE) {
-                final String subscriberId = template.getSubscriberIds().isEmpty() ? null
-                        : template.getSubscriberIds().iterator().next();
-                onThresholdReached(networkType, subscriberId);
-            }
-        }
-
-        /**
-         * Called when data usage has reached the given threshold.
-         */
-        public abstract void onThresholdReached(int networkType, String subscriberId);
-
-        /**
-         * @hide used for internal bookkeeping
-         */
-        private DataUsageRequest request;
-
-        /**
-         * Get network type from a template if feasible.
-         *
-         * @param template the target {@link NetworkTemplate}.
-         * @return legacy network type, only supports for the types which is already supported in
-         *         {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}.
-         *         {@link ConnectivityManager#TYPE_NONE} for other types.
-         */
-        private static int networkTypeForTemplate(@NonNull NetworkTemplate template) {
-            switch (template.getMatchRule()) {
-                case NetworkTemplate.MATCH_MOBILE:
-                    return ConnectivityManager.TYPE_MOBILE;
-                case NetworkTemplate.MATCH_WIFI:
-                    return ConnectivityManager.TYPE_WIFI;
-                default:
-                    return ConnectivityManager.TYPE_NONE;
-            }
-        }
-    }
-
-    /**
-     * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
-     * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
-     * Note that no de-duplication of statistics between providers is performed, so each provider
-     * must only report network traffic that is not being reported by any other provider. Also note
-     * that the provider cannot be re-registered after unregistering.
-     *
-     * @param tag a human readable identifier of the custom network stats provider. This is only
-     *            used for debugging.
-     * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
-     *                 registered to the system.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            android.Manifest.permission.NETWORK_STATS_PROVIDER,
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
-    @NonNull public void registerNetworkStatsProvider(
-            @NonNull String tag,
-            @NonNull NetworkStatsProvider provider) {
-        try {
-            if (provider.getProviderCallbackBinder() != null) {
-                throw new IllegalArgumentException("provider is already registered");
-            }
-            final INetworkStatsProviderCallback cbBinder =
-                    mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
-            provider.setProviderCallbackBinder(cbBinder);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Unregisters an instance of {@link NetworkStatsProvider}.
-     *
-     * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
-     *                 unregistered to the system.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            android.Manifest.permission.NETWORK_STATS_PROVIDER,
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
-    @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
-        try {
-            provider.getProviderCallbackBinderOrThrow().unregister();
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
-        final NetworkTemplate template;
-        switch (networkType) {
-            case ConnectivityManager.TYPE_MOBILE:
-                template = subscriberId == null
-                        ? NetworkTemplate.buildTemplateMobileWildcard()
-                        : NetworkTemplate.buildTemplateMobileAll(subscriberId);
-                break;
-            case ConnectivityManager.TYPE_WIFI:
-                template = TextUtils.isEmpty(subscriberId)
-                        ? NetworkTemplate.buildTemplateWifiWildcard()
-                        : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL,
-                                subscriberId);
-                break;
-            default:
-                throw new IllegalArgumentException("Cannot create template for network type "
-                        + networkType + ", subscriberId '"
-                        + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + "'.");
-        }
-        return template;
-    }
-
-    /**
-     * Notify {@code NetworkStatsService} about network status changed.
-     *
-     * Notifies NetworkStatsService of network state changes for data usage accounting purposes.
-     *
-     * To avoid races that attribute data usage to wrong network, such as new network with
-     * the same interface after SIM hot-swap, this function will not return until
-     * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from
-     * all data sources.
-     *
-     * @param defaultNetworks the list of all networks that could be used by network traffic that
-     *                        does not explicitly select a network.
-     * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for
-     *                              each network that is currently connected.
-     * @param activeIface the active (i.e., connected) default network interface for the calling
-     *                    uid. Used to determine on which network future calls to
-     *                    {@link android.net.TrafficStats#incrementOperationCount} applies to.
-     * @param underlyingNetworkInfos the list of underlying network information for all
-     *                               currently-connected VPNs.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    public void notifyNetworkStatus(
-            @NonNull List<Network> defaultNetworks,
-            @NonNull List<NetworkStateSnapshot> networkStateSnapshots,
-            @Nullable String activeIface,
-            @NonNull List<UnderlyingNetworkInfo> underlyingNetworkInfos) {
-        try {
-            Objects.requireNonNull(defaultNetworks);
-            Objects.requireNonNull(networkStateSnapshots);
-            Objects.requireNonNull(underlyingNetworkInfos);
-            mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]),
-                    networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface,
-                    underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0]));
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    private static class UsageCallbackWrapper extends IUsageCallback.Stub {
-        // Null if unregistered.
-        private volatile UsageCallback mCallback;
-
-        private final Executor mExecutor;
-
-        UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) {
-            mCallback = callback;
-            mExecutor = executor;
-        }
-
-        @Override
-        public void onThresholdReached(DataUsageRequest request) {
-            // Copy it to a local variable in case mCallback changed inside the if condition.
-            final UsageCallback callback = mCallback;
-            if (callback != null) {
-                mExecutor.execute(() -> callback.onThresholdReached(request.template));
-            } else {
-                Log.e(TAG, "onThresholdReached with released callback for " + request);
-            }
-        }
-
-        @Override
-        public void onCallbackReleased(DataUsageRequest request) {
-            if (DBG) Log.d(TAG, "callback released for " + request);
-            mCallback = null;
-        }
-    }
-
-    /**
-     * Mark given UID as being in foreground for stats purposes.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    public void noteUidForeground(int uid, boolean uidForeground) {
-        try {
-            mService.noteUidForeground(uid, uidForeground);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB].
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            Manifest.permission.NETWORK_STACK})
-    public void setDefaultGlobalAlert(long alertBytes) {
-        try {
-            // TODO: Sync internal naming with the API surface.
-            mService.advisePersistThreshold(alertBytes);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Force update of statistics.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    public void forceUpdate() {
-        try {
-            mService.forceUpdate();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Set the warning and limit to all registered custom network stats providers.
-     * Note that invocation of any interface will be sent to all providers.
-     *
-     * Asynchronicity notes : because traffic may be happening on the device at the same time, it
-     * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't
-     * know when exactly it was effective. All that can matter is that it's done quickly. Also,
-     * this method can't fail, so there is no status to return. All providers will see the new
-     * values soon.
-     * As such, this method returns immediately and sends the warning and limit to all providers
-     * as soon as possible through a one-way binder call.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK})
-    public void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning,
-            long limit) {
-        try {
-            mService.setStatsProviderWarningAndLimitAsync(iface, warning, limit);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get a RAT type representative of a group of RAT types for network statistics.
-     *
-     * Collapse the given Radio Access Technology (RAT) type into a bucket that
-     * is representative of the original RAT type for network statistics. The
-     * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}
-     * but with adaptations specific to the virtual types introduced by
-     * networks stats.
-     *
-     * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static int getCollapsedRatType(int ratType) {
-        switch (ratType) {
-            case TelephonyManager.NETWORK_TYPE_GPRS:
-            case TelephonyManager.NETWORK_TYPE_GSM:
-            case TelephonyManager.NETWORK_TYPE_EDGE:
-            case TelephonyManager.NETWORK_TYPE_IDEN:
-            case TelephonyManager.NETWORK_TYPE_CDMA:
-            case TelephonyManager.NETWORK_TYPE_1xRTT:
-                return TelephonyManager.NETWORK_TYPE_GSM;
-            case TelephonyManager.NETWORK_TYPE_EVDO_0:
-            case TelephonyManager.NETWORK_TYPE_EVDO_A:
-            case TelephonyManager.NETWORK_TYPE_EVDO_B:
-            case TelephonyManager.NETWORK_TYPE_EHRPD:
-            case TelephonyManager.NETWORK_TYPE_UMTS:
-            case TelephonyManager.NETWORK_TYPE_HSDPA:
-            case TelephonyManager.NETWORK_TYPE_HSUPA:
-            case TelephonyManager.NETWORK_TYPE_HSPA:
-            case TelephonyManager.NETWORK_TYPE_HSPAP:
-            case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
-                return TelephonyManager.NETWORK_TYPE_UMTS;
-            case TelephonyManager.NETWORK_TYPE_LTE:
-            case TelephonyManager.NETWORK_TYPE_IWLAN:
-                return TelephonyManager.NETWORK_TYPE_LTE;
-            case TelephonyManager.NETWORK_TYPE_NR:
-                return TelephonyManager.NETWORK_TYPE_NR;
-            // Virtual RAT type for 5G NSA mode, see
-            // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
-            case NetworkStatsManager.NETWORK_TYPE_5G_NSA:
-                return NetworkStatsManager.NETWORK_TYPE_5G_NSA;
-            default:
-                return TelephonyManager.NETWORK_TYPE_UNKNOWN;
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
deleted file mode 100644
index 61b34d0..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.SystemApi;
-import android.app.SystemServiceRegistry;
-import android.app.usage.NetworkStatsManager;
-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 NetworkStats, nsd,
-     * ipsec and ethernet 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);
-                }
-        );
-
-        SystemServiceRegistry.registerContextAwareService(
-                Context.IPSEC_SERVICE,
-                IpSecManager.class,
-                (context, serviceBinder) -> {
-                    IIpSecService service = IIpSecService.Stub.asInterface(serviceBinder);
-                    return new IpSecManager(context, service);
-                }
-        );
-
-        SystemServiceRegistry.registerContextAwareService(
-                Context.NETWORK_STATS_SERVICE,
-                NetworkStatsManager.class,
-                (context, serviceBinder) -> {
-                    INetworkStatsService service =
-                            INetworkStatsService.Stub.asInterface(serviceBinder);
-                    return new NetworkStatsManager(context, service);
-                }
-        );
-
-        SystemServiceRegistry.registerContextAwareService(
-                Context.ETHERNET_SERVICE,
-                EthernetManager.class,
-                (context, serviceBinder) -> {
-                    IEthernetManager service = IEthernetManager.Stub.asInterface(serviceBinder);
-                    return new EthernetManager(context, service);
-                }
-        );
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl
deleted file mode 100644
index d1937c7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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;
-
-parcelable DataUsageRequest;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
deleted file mode 100644
index b06d515..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/**
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy
- * of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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.Nullable;
-import android.net.NetworkTemplate;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Defines a request to register a callbacks. Used to be notified on data usage via
- * {@link android.app.usage.NetworkStatsManager#registerDataUsageCallback}.
- * If no {@code uid}s are set, callbacks are restricted to device-owners,
- * carrier-privileged apps, or system apps.
- *
- * @hide
- */
-public final class DataUsageRequest implements Parcelable {
-
-    public static final String PARCELABLE_KEY = "DataUsageRequest";
-    public static final int REQUEST_ID_UNSET = 0;
-
-    /**
-     * Identifies the request.  {@link DataUsageRequest}s should only be constructed by
-     * the Framework and it is used internally to identify the request.
-     */
-    public final int requestId;
-
-    /**
-     * {@link NetworkTemplate} describing the network to monitor.
-     */
-    public final NetworkTemplate template;
-
-    /**
-     * Threshold in bytes to be notified on.
-     */
-    public final long thresholdInBytes;
-
-    public DataUsageRequest(int requestId, NetworkTemplate template, long thresholdInBytes) {
-        this.requestId = requestId;
-        this.template = template;
-        this.thresholdInBytes = thresholdInBytes;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(requestId);
-        dest.writeParcelable(template, flags);
-        dest.writeLong(thresholdInBytes);
-    }
-
-    public static final @android.annotation.NonNull Creator<DataUsageRequest> CREATOR =
-            new Creator<DataUsageRequest>() {
-                @Override
-                public DataUsageRequest createFromParcel(Parcel in) {
-                    int requestId = in.readInt();
-                    NetworkTemplate template = in.readParcelable(null);
-                    long thresholdInBytes = in.readLong();
-                    DataUsageRequest result = new DataUsageRequest(requestId, template,
-                            thresholdInBytes);
-                    return result;
-                }
-
-                @Override
-                public DataUsageRequest[] newArray(int size) {
-                    return new DataUsageRequest[size];
-                }
-            };
-
-    @Override
-    public String toString() {
-        return "DataUsageRequest [ requestId=" + requestId
-                + ", networkTemplate=" + template
-                + ", thresholdInBytes=" + thresholdInBytes + " ]";
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (obj instanceof DataUsageRequest == false) return false;
-        DataUsageRequest that = (DataUsageRequest) obj;
-        return that.requestId == this.requestId
-                && Objects.equals(that.template, this.template)
-                && that.thresholdInBytes == this.thresholdInBytes;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(requestId, template, thresholdInBytes);
-   }
-
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
deleted file mode 100644
index e02ea89..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.OutcomeReceiver;
-import android.os.RemoteException;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.modules.utils.BackgroundThread;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.function.IntConsumer;
-
-/**
- * A class that manages and configures Ethernet interfaces.
- *
- * @hide
- */
-@SystemApi
-@SystemService(Context.ETHERNET_SERVICE)
-public class EthernetManager {
-    private static final String TAG = "EthernetManager";
-
-    private final IEthernetManager mService;
-    @GuardedBy("mListenerLock")
-    private final ArrayList<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
-            new ArrayList<>();
-    @GuardedBy("mListenerLock")
-    private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
-            new ArrayList<>();
-    final Object mListenerLock = new Object();
-    private final IEthernetServiceListener.Stub mServiceListener =
-            new IEthernetServiceListener.Stub() {
-                @Override
-                public void onEthernetStateChanged(int state) {
-                    synchronized (mListenerLock) {
-                        for (ListenerInfo<IntConsumer> li : mEthernetStateListeners) {
-                            li.executor.execute(() -> {
-                                li.listener.accept(state);
-                            });
-                        }
-                    }
-                }
-
-                @Override
-                public void onInterfaceStateChanged(String iface, int state, int role,
-                        IpConfiguration configuration) {
-                    synchronized (mListenerLock) {
-                        for (ListenerInfo<InterfaceStateListener> li : mIfaceListeners) {
-                            li.executor.execute(() ->
-                                    li.listener.onInterfaceStateChanged(iface, state, role,
-                                            configuration));
-                        }
-                    }
-                }
-            };
-
-    /**
-     * Indicates that Ethernet is disabled.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int ETHERNET_STATE_DISABLED = 0;
-
-    /**
-     * Indicates that Ethernet is enabled.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int ETHERNET_STATE_ENABLED  = 1;
-
-    private static class ListenerInfo<T> {
-        @NonNull
-        public final Executor executor;
-        @NonNull
-        public final T listener;
-
-        private ListenerInfo(@NonNull Executor executor, @NonNull T listener) {
-            this.executor = executor;
-            this.listener = listener;
-        }
-    }
-
-    /**
-     * The interface is absent.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int STATE_ABSENT = 0;
-
-    /**
-     * The interface is present but link is down.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int STATE_LINK_DOWN = 1;
-
-    /**
-     * The interface is present and link is up.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int STATE_LINK_UP = 2;
-
-    /** @hide */
-    @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface InterfaceState {}
-
-    /**
-     * The interface currently does not have any specific role.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int ROLE_NONE = 0;
-
-    /**
-     * The interface is in client mode (e.g., connected to the Internet).
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int ROLE_CLIENT = 1;
-
-    /**
-     * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int ROLE_SERVER = 2;
-
-    /** @hide */
-    @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Role {}
-
-    /**
-     * A listener that receives notifications about the state of Ethernet interfaces on the system.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public interface InterfaceStateListener {
-        /**
-         * Called when an Ethernet interface changes state.
-         *
-         * @param iface the name of the interface.
-         * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
-         *              interface was removed.
-         * @param role whether the interface is in client mode or server mode.
-         * @param configuration the current IP configuration of the interface.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
-                @Role int role, @Nullable IpConfiguration configuration);
-    }
-
-    /**
-     * A listener interface to receive notification on changes in Ethernet.
-     * This has never been a supported API. Use {@link InterfaceStateListener} instead.
-     * @hide
-     */
-    public interface Listener extends InterfaceStateListener {
-        /**
-         * Called when Ethernet port's availability is changed.
-         * @param iface Ethernet interface name
-         * @param isAvailable {@code true} if Ethernet port exists.
-         * @hide
-         */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        void onAvailabilityChanged(String iface, boolean isAvailable);
-
-        /** Default implementation for backwards compatibility. Only calls the legacy listener. */
-        default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
-                @Role int role, @Nullable IpConfiguration configuration) {
-            onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
-        }
-
-    }
-
-    /**
-     * Create a new EthernetManager instance.
-     * Applications will almost always want to use
-     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
-     * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
-     * @hide
-     */
-    public EthernetManager(Context context, IEthernetManager service) {
-        mService = service;
-    }
-
-    /**
-     * Get Ethernet configuration.
-     * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public IpConfiguration getConfiguration(String iface) {
-        try {
-            return mService.getConfiguration(iface);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Set Ethernet configuration.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
-        try {
-            mService.setConfiguration(iface, config);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Indicates whether the system currently has one or more Ethernet interfaces.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean isAvailable() {
-        return getAvailableInterfaces().length > 0;
-    }
-
-    /**
-     * Indicates whether the system has given interface.
-     *
-     * @param iface Ethernet interface name
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public boolean isAvailable(String iface) {
-        try {
-            return mService.isAvailable(iface);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Adds a listener.
-     * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
-     *
-     * @param listener A {@link Listener} to add.
-     * @throws IllegalArgumentException If the listener is null.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void addListener(@NonNull Listener listener) {
-        addListener(listener, BackgroundThread.getExecutor());
-    }
-
-    /**
-     * Adds a listener.
-     * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
-     *
-     * @param listener A {@link Listener} to add.
-     * @param executor Executor to run callbacks on.
-     * @throws IllegalArgumentException If the listener or executor is null.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
-        addInterfaceStateListener(executor, listener);
-    }
-
-    /**
-     * Listen to changes in the state of Ethernet interfaces.
-     *
-     * Adds a listener to receive notification for any state change of all existing Ethernet
-     * interfaces.
-     * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
-     * existing interfaces upon adding a listener. The same method will be called on the
-     * listener every time any of the interface changes state. In particular, if an
-     * interface is removed, it will be called with state {@link #STATE_ABSENT}.
-     * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
-     *
-     * @param executor Executor to run callbacks on.
-     * @param listener A {@link Listener} to add.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void addInterfaceStateListener(@NonNull Executor executor,
-            @NonNull InterfaceStateListener listener) {
-        if (listener == null || executor == null) {
-            throw new NullPointerException("listener and executor must not be null");
-        }
-        synchronized (mListenerLock) {
-            maybeAddServiceListener();
-            mIfaceListeners.add(new ListenerInfo<InterfaceStateListener>(executor, listener));
-        }
-    }
-
-    @GuardedBy("mListenerLock")
-    private void maybeAddServiceListener() {
-        if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
-
-        try {
-            mService.addListener(mServiceListener);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-
-    }
-
-    /**
-     * Returns an array of available Ethernet interface names.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public String[] getAvailableInterfaces() {
-        try {
-            return mService.getAvailableInterfaces();
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Removes a listener.
-     *
-     * @param listener A {@link Listener} to remove.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
-        Objects.requireNonNull(listener);
-        synchronized (mListenerLock) {
-            mIfaceListeners.removeIf(l -> l.listener == listener);
-            maybeRemoveServiceListener();
-        }
-    }
-
-    @GuardedBy("mListenerLock")
-    private void maybeRemoveServiceListener() {
-        if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
-
-        try {
-            mService.removeListener(mServiceListener);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Removes a listener.
-     * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
-     * @param listener A {@link Listener} to remove.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public void removeListener(@NonNull Listener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("listener must not be null");
-        }
-        removeInterfaceStateListener(listener);
-    }
-
-    /**
-     * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
-     * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
-     * already present on the system.
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void setIncludeTestInterfaces(boolean include) {
-        try {
-            mService.setIncludeTestInterfaces(include);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * A request for a tethered interface.
-     */
-    public static class TetheredInterfaceRequest {
-        private final IEthernetManager mService;
-        private final ITetheredInterfaceCallback mCb;
-
-        private TetheredInterfaceRequest(@NonNull IEthernetManager service,
-                @NonNull ITetheredInterfaceCallback cb) {
-            this.mService = service;
-            this.mCb = cb;
-        }
-
-        /**
-         * Release the request, causing the interface to revert back from tethering mode if there
-         * is no other requestor.
-         */
-        public void release() {
-            try {
-                mService.releaseTetheredInterface(mCb);
-            } catch (RemoteException e) {
-                e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
-     * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
-     */
-    public interface TetheredInterfaceCallback {
-        /**
-         * Called when the tethered interface is available.
-         * @param iface The name of the interface.
-         */
-        void onAvailable(@NonNull String iface);
-
-        /**
-         * Called when the tethered interface is now unavailable.
-         */
-        void onUnavailable();
-    }
-
-    /**
-     * Request a tethered interface in tethering mode.
-     *
-     * <p>When this method is called and there is at least one ethernet interface available, the
-     * system will designate one to act as a tethered interface. If there is already a tethered
-     * interface, the existing interface will be used.
-     * @param callback A callback to be called once the request has been fulfilled.
-     */
-    @RequiresPermission(anyOf = {
-            android.Manifest.permission.NETWORK_STACK,
-            android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
-    })
-    @NonNull
-    public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
-            @NonNull final TetheredInterfaceCallback callback) {
-        Objects.requireNonNull(callback, "Callback must be non-null");
-        Objects.requireNonNull(executor, "Executor must be non-null");
-        final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
-            @Override
-            public void onAvailable(String iface) {
-                executor.execute(() -> callback.onAvailable(iface));
-            }
-
-            @Override
-            public void onUnavailable() {
-                executor.execute(() -> callback.onUnavailable());
-            }
-        };
-
-        try {
-            mService.requestTetheredInterface(cbInternal);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-        return new TetheredInterfaceRequest(mService, cbInternal);
-    }
-
-    private static final class NetworkInterfaceOutcomeReceiver
-            extends INetworkInterfaceOutcomeReceiver.Stub {
-        @NonNull
-        private final Executor mExecutor;
-        @NonNull
-        private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
-
-        NetworkInterfaceOutcomeReceiver(
-                @NonNull final Executor executor,
-                @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
-                        callback) {
-            Objects.requireNonNull(executor, "Pass a non-null executor");
-            Objects.requireNonNull(callback, "Pass a non-null callback");
-            mExecutor = executor;
-            mCallback = callback;
-        }
-
-        @Override
-        public void onResult(@NonNull String iface) {
-            mExecutor.execute(() -> mCallback.onResult(iface));
-        }
-
-        @Override
-        public void onError(@NonNull EthernetNetworkManagementException e) {
-            mExecutor.execute(() -> mCallback.onError(e));
-        }
-    }
-
-    private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
-            @Nullable final Executor executor,
-            @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
-        if (null != callback) {
-            Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
-        }
-        final NetworkInterfaceOutcomeReceiver proxy;
-        if (null == callback) {
-            proxy = null;
-        } else {
-            proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
-        }
-        return proxy;
-    }
-
-    /**
-     * Updates the configuration of an automotive device's ethernet network.
-     *
-     * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
-     * configuration for this network.
-     * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
-     * this network to put inside the {@code request}.
-     * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
-     * object for this network to put inside the {@code request}.
-     *
-     * This function accepts an {@link OutcomeReceiver} that is called once the operation has
-     * finished execution.
-     *
-     * @param iface the name of the interface to act upon.
-     * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
-     *                {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
-     * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
-     * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
-     *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
-     *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
-     *                 information about the error.
-     * @throws SecurityException if the process doesn't hold
-     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
-     * @throws UnsupportedOperationException if called on a non-automotive device or on an
-     *                                       unsupported interface.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK,
-            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
-    public void updateConfiguration(
-            @NonNull String iface,
-            @NonNull EthernetNetworkUpdateRequest request,
-            @Nullable @CallbackExecutor Executor executor,
-            @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
-        Objects.requireNonNull(iface, "iface must be non-null");
-        Objects.requireNonNull(request, "request must be non-null");
-        final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
-                executor, callback);
-        try {
-            mService.updateConfiguration(iface, request, proxy);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Enable a network interface.
-     *
-     * Enables a previously disabled network interface.
-     * This function accepts an {@link OutcomeReceiver} that is called once the operation has
-     * finished execution.
-     *
-     * @param iface the name of the interface to enable.
-     * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
-     * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
-     *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
-     *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
-     *                 information about the error.
-     * @throws SecurityException if the process doesn't hold
-     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK,
-            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
-    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
-    public void enableInterface(
-            @NonNull String iface,
-            @Nullable @CallbackExecutor Executor executor,
-            @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
-        Objects.requireNonNull(iface, "iface must be non-null");
-        final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
-                executor, callback);
-        try {
-            mService.connectNetwork(iface, proxy);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Disable a network interface.
-     *
-     * Disables the use of a network interface to fulfill network requests. If the interface
-     * currently serves a request, the network will be torn down.
-     * This function accepts an {@link OutcomeReceiver} that is called once the operation has
-     * finished execution.
-     *
-     * @param iface the name of the interface to disable.
-     * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
-     * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
-     *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
-     *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
-     *                 information about the error.
-     * @throws SecurityException if the process doesn't hold
-     *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK,
-            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
-    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
-    public void disableInterface(
-            @NonNull String iface,
-            @Nullable @CallbackExecutor Executor executor,
-            @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
-        Objects.requireNonNull(iface, "iface must be non-null");
-        final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
-                executor, callback);
-        try {
-            mService.disconnectNetwork(iface, proxy);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Change ethernet setting.
-     *
-     * @param enabled enable or disable ethernet settings.
-     *
-     * @hide
-     */
-    @RequiresPermission(anyOf = {
-            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-            android.Manifest.permission.NETWORK_STACK,
-            android.Manifest.permission.NETWORK_SETTINGS})
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void setEthernetEnabled(boolean enabled) {
-        try {
-            mService.setEthernetEnabled(enabled);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Listen to changes in the state of ethernet.
-     *
-     * @param executor to run callbacks on.
-     * @param listener to listen ethernet state changed.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void addEthernetStateListener(@NonNull Executor executor,
-            @NonNull IntConsumer listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
-        synchronized (mListenerLock) {
-            maybeAddServiceListener();
-            mEthernetStateListeners.add(new ListenerInfo<IntConsumer>(executor, listener));
-        }
-    }
-
-    /**
-     * Removes a listener.
-     *
-     * @param listener to listen ethernet state changed.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    @SystemApi(client = MODULE_LIBRARIES)
-    public void removeEthernetStateListener(@NonNull IntConsumer listener) {
-        Objects.requireNonNull(listener);
-        synchronized (mListenerLock) {
-            mEthernetStateListeners.removeIf(l -> l.listener == listener);
-            maybeRemoveServiceListener();
-        }
-    }
-
-    /**
-     * Returns an array of existing Ethernet interface names regardless whether the interface
-     * is available or not currently.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    @SystemApi(client = MODULE_LIBRARIES)
-    @NonNull
-    public List<String> getInterfaceList() {
-        try {
-            return mService.getInterfaceList();
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
deleted file mode 100644
index adf9e5a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package android.net;
-
- parcelable EthernetNetworkManagementException;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
deleted file mode 100644
index a69cc55..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/** @hide */
-@SystemApi
-public final class EthernetNetworkManagementException
-        extends RuntimeException implements Parcelable {
-
-    /* @hide */
-    public EthernetNetworkManagementException(@NonNull final String errorMessage) {
-        super(errorMessage);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(getMessage());
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null || getClass() != obj.getClass()) return false;
-        final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj;
-
-        return Objects.equals(getMessage(), that.getMessage());
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(getMessage());
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
-            new Parcelable.Creator<EthernetNetworkManagementException>() {
-                @Override
-                public EthernetNetworkManagementException[] newArray(int size) {
-                    return new EthernetNetworkManagementException[size];
-                }
-
-                @Override
-                public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
-                    return new EthernetNetworkManagementException(source.readString());
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
deleted file mode 100644
index e4d6e24..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.Objects;
-
-/**
- * A {@link NetworkSpecifier} used to identify ethernet interfaces.
- *
- * @see EthernetManager
- */
-public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable {
-
-    /**
-     * Name of the network interface.
-     */
-    @NonNull
-    private final String mInterfaceName;
-
-    /**
-     * Create a new EthernetNetworkSpecifier.
-     * @param interfaceName Name of the ethernet interface the specifier refers to.
-     */
-    public EthernetNetworkSpecifier(@NonNull String interfaceName) {
-        if (TextUtils.isEmpty(interfaceName)) {
-            throw new IllegalArgumentException();
-        }
-        mInterfaceName = interfaceName;
-    }
-
-    /**
-     * Get the name of the ethernet interface the specifier refers to.
-     */
-    @Nullable
-    public String getInterfaceName() {
-        // This may be null in the future to support specifiers based on data other than the
-        // interface name.
-        return mInterfaceName;
-    }
-
-    /** @hide */
-    @Override
-    public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
-        return equals(other);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object o) {
-        if (!(o instanceof EthernetNetworkSpecifier)) return false;
-        return TextUtils.equals(mInterfaceName, ((EthernetNetworkSpecifier) o).mInterfaceName);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(mInterfaceName);
-    }
-
-    @Override
-    public String toString() {
-        return "EthernetNetworkSpecifier (" + mInterfaceName + ")";
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mInterfaceName);
-    }
-
-    public static final @NonNull Parcelable.Creator<EthernetNetworkSpecifier> CREATOR =
-            new Parcelable.Creator<EthernetNetworkSpecifier>() {
-        public EthernetNetworkSpecifier createFromParcel(Parcel in) {
-            return new EthernetNetworkSpecifier(in.readString());
-        }
-        public EthernetNetworkSpecifier[] newArray(int size) {
-            return new EthernetNetworkSpecifier[size];
-        }
-    };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
deleted file mode 100644
index debc348..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package android.net;
-
- parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
deleted file mode 100644
index 1691942..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * Represents a request to update an existing Ethernet interface.
- *
- * @see EthernetManager#updateConfiguration
- *
- * @hide
- */
-@SystemApi
-public final class EthernetNetworkUpdateRequest implements Parcelable {
-    @Nullable
-    private final IpConfiguration mIpConfig;
-    @Nullable
-    private final NetworkCapabilities mNetworkCapabilities;
-
-    /**
-     * Setting the {@link IpConfiguration} is optional in {@link EthernetNetworkUpdateRequest}.
-     * When set to null, the existing IpConfiguration is not updated.
-     *
-     * @return the new {@link IpConfiguration} or null.
-     */
-    @Nullable
-    public IpConfiguration getIpConfiguration() {
-        return mIpConfig == null ? null : new IpConfiguration(mIpConfig);
-    }
-
-    /**
-     * Setting the {@link NetworkCapabilities} is optional in {@link EthernetNetworkUpdateRequest}.
-     * When set to null, the existing NetworkCapabilities are not updated.
-     *
-     * @return the new {@link NetworkCapabilities} or null.
-     */
-    @Nullable
-    public NetworkCapabilities getNetworkCapabilities() {
-        return mNetworkCapabilities == null ? null : new NetworkCapabilities(mNetworkCapabilities);
-    }
-
-    private EthernetNetworkUpdateRequest(@Nullable final IpConfiguration ipConfig,
-            @Nullable final NetworkCapabilities networkCapabilities) {
-        mIpConfig = ipConfig;
-        mNetworkCapabilities = networkCapabilities;
-    }
-
-    private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
-        Objects.requireNonNull(source);
-        mIpConfig = source.readParcelable(IpConfiguration.class.getClassLoader(),
-                IpConfiguration.class);
-        mNetworkCapabilities = source.readParcelable(NetworkCapabilities.class.getClassLoader(),
-                NetworkCapabilities.class);
-    }
-
-    /**
-     * Builder used to create {@link EthernetNetworkUpdateRequest} objects.
-     */
-    public static final class Builder {
-        @Nullable
-        private IpConfiguration mBuilderIpConfig;
-        @Nullable
-        private NetworkCapabilities mBuilderNetworkCapabilities;
-
-        public Builder(){}
-
-        /**
-         * Constructor to populate the builder's values with an already built
-         * {@link EthernetNetworkUpdateRequest}.
-         * @param request the {@link EthernetNetworkUpdateRequest} to populate with.
-         */
-        public Builder(@NonNull final EthernetNetworkUpdateRequest request) {
-            Objects.requireNonNull(request);
-            mBuilderIpConfig = null == request.mIpConfig
-                    ? null : new IpConfiguration(request.mIpConfig);
-            mBuilderNetworkCapabilities = null == request.mNetworkCapabilities
-                    ? null : new NetworkCapabilities(request.mNetworkCapabilities);
-        }
-
-        /**
-         * Set the {@link IpConfiguration} to be used with the {@code Builder}.
-         * @param ipConfig the {@link IpConfiguration} to set.
-         * @return The builder to facilitate chaining.
-         */
-        @NonNull
-        public Builder setIpConfiguration(@Nullable final IpConfiguration ipConfig) {
-            mBuilderIpConfig = ipConfig == null ? null : new IpConfiguration(ipConfig);
-            return this;
-        }
-
-        /**
-         * Set the {@link NetworkCapabilities} to be used with the {@code Builder}.
-         * @param nc the {@link NetworkCapabilities} to set.
-         * @return The builder to facilitate chaining.
-         */
-        @NonNull
-        public Builder setNetworkCapabilities(@Nullable final NetworkCapabilities nc) {
-            mBuilderNetworkCapabilities = nc == null ? null : new NetworkCapabilities(nc);
-            return this;
-        }
-
-        /**
-         * Build {@link EthernetNetworkUpdateRequest} return the current update request.
-         *
-         * @throws IllegalStateException when both mBuilderNetworkCapabilities and mBuilderIpConfig
-         *                               are null.
-         */
-        @NonNull
-        public EthernetNetworkUpdateRequest build() {
-            if (mBuilderIpConfig == null && mBuilderNetworkCapabilities == null) {
-                throw new IllegalStateException(
-                        "Cannot construct an empty EthernetNetworkUpdateRequest");
-            }
-            return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "EthernetNetworkUpdateRequest{"
-                + "mIpConfig=" + mIpConfig
-                + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
-
-        return Objects.equals(that.getIpConfiguration(), mIpConfig)
-                && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mIpConfig, mNetworkCapabilities);
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeParcelable(mIpConfig, flags);
-        dest.writeParcelable(mNetworkCapabilities, flags);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
-            new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
-                @Override
-                public EthernetNetworkUpdateRequest[] newArray(int size) {
-                    return new EthernetNetworkUpdateRequest[size];
-                }
-
-                @Override
-                public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
-                    return new EthernetNetworkUpdateRequest(source);
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
deleted file mode 100644
index 42e4c1a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.IpConfiguration;
-import android.net.IEthernetServiceListener;
-import android.net.EthernetNetworkManagementException;
-import android.net.EthernetNetworkUpdateRequest;
-import android.net.INetworkInterfaceOutcomeReceiver;
-import android.net.ITetheredInterfaceCallback;
-
-import java.util.List;
-
-/**
- * Interface that answers queries about, and allows changing
- * ethernet configuration.
- */
-/** {@hide} */
-interface IEthernetManager
-{
-    String[] getAvailableInterfaces();
-    IpConfiguration getConfiguration(String iface);
-    void setConfiguration(String iface, in IpConfiguration config);
-    boolean isAvailable(String iface);
-    void addListener(in IEthernetServiceListener listener);
-    void removeListener(in IEthernetServiceListener listener);
-    void setIncludeTestInterfaces(boolean include);
-    void requestTetheredInterface(in ITetheredInterfaceCallback callback);
-    void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
-    void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
-        in INetworkInterfaceOutcomeReceiver listener);
-    void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
-    void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
-    void setEthernetEnabled(boolean enabled);
-    List<String> getInterfaceList();
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
deleted file mode 100644
index 751605b..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.IpConfiguration;
-
-/** @hide */
-oneway interface IEthernetServiceListener
-{
-    void onEthernetStateChanged(int state);
-    void onInterfaceStateChanged(String iface, int state, int role,
-            in IpConfiguration configuration);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl b/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl
deleted file mode 100644
index 933256a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-package android.net;
-
-import android.net.LinkAddress;
-import android.net.Network;
-import android.net.IpSecConfig;
-import android.net.IpSecUdpEncapResponse;
-import android.net.IpSecSpiResponse;
-import android.net.IpSecTransformResponse;
-import android.net.IpSecTunnelInterfaceResponse;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-
-/**
- * @hide
- */
-interface IIpSecService
-{
-    IpSecSpiResponse allocateSecurityParameterIndex(
-            in String destinationAddress, int requestedSpi, in IBinder binder);
-
-    void releaseSecurityParameterIndex(int resourceId);
-
-    IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, in IBinder binder);
-
-    void closeUdpEncapsulationSocket(int resourceId);
-
-    IpSecTunnelInterfaceResponse createTunnelInterface(
-            in String localAddr,
-            in String remoteAddr,
-            in Network underlyingNetwork,
-            in IBinder binder,
-            in String callingPackage);
-
-    void addAddressToTunnelInterface(
-            int tunnelResourceId,
-            in LinkAddress localAddr,
-            in String callingPackage);
-
-    void removeAddressFromTunnelInterface(
-            int tunnelResourceId,
-            in LinkAddress localAddr,
-            in String callingPackage);
-
-    void setNetworkForTunnelInterface(
-            int tunnelResourceId, in Network underlyingNetwork, in String callingPackage);
-
-    void deleteTunnelInterface(int resourceId, in String callingPackage);
-
-    IpSecTransformResponse createTransform(
-            in IpSecConfig c, in IBinder binder, in String callingPackage);
-
-    void deleteTransform(int transformId);
-
-    void applyTransportModeTransform(
-            in ParcelFileDescriptor socket, int direction, int transformId);
-
-    void applyTunnelModeTransform(
-            int tunnelResourceId, int direction, int transformResourceId, in String callingPackage);
-
-    void removeTransportModeTransforms(in ParcelFileDescriptor socket);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl
deleted file mode 100644
index 85795ea..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.EthernetNetworkManagementException;
-
-/** @hide */
-oneway interface INetworkInterfaceOutcomeReceiver {
-    void onResult(in String iface);
-    void onError(in EthernetNetworkManagementException e);
-}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
deleted file mode 100644
index c86f7fd..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.DataUsageRequest;
-import android.net.INetworkStatsSession;
-import android.net.Network;
-import android.net.NetworkStateSnapshot;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.UnderlyingNetworkInfo;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.provider.INetworkStatsProvider;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.os.IBinder;
-import android.os.Messenger;
-
-/** {@hide} */
-interface INetworkStatsService {
-
-    /** Start a statistics query session. */
-    @UnsupportedAppUsage
-    INetworkStatsSession openSession();
-
-    /** Start a statistics query session. If calling package is profile or device owner then it is
-     *  granted automatic access if apiLevel is NetworkStatsManager.API_LEVEL_DPC_ALLOWED. If
-     *  apiLevel is at least NetworkStatsManager.API_LEVEL_REQUIRES_PACKAGE_USAGE_STATS then
-     *  PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted
-     *  READ_NETWORK_USAGE_STATS is checked for.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage);
-
-    /** Return data layer snapshot of UID network usage. */
-    @UnsupportedAppUsage
-    NetworkStats getDataLayerSnapshotForUid(int uid);
-
-    /** Get the transport NetworkStats for all UIDs since boot. */
-    NetworkStats getUidStatsForTransport(int transport);
-
-    /** Return set of any ifaces associated with mobile networks since boot. */
-    @UnsupportedAppUsage
-    String[] getMobileIfaces();
-
-    /** Increment data layer count of operations performed for UID and tag. */
-    void incrementOperationCount(int uid, int tag, int operationCount);
-
-    /**  Notify {@code NetworkStatsService} about network status changed. */
-    void notifyNetworkStatus(
-         in Network[] defaultNetworks,
-         in NetworkStateSnapshot[] snapshots,
-         in String activeIface,
-         in UnderlyingNetworkInfo[] underlyingNetworkInfos);
-    /** Force update of statistics. */
-    @UnsupportedAppUsage
-    void forceUpdate();
-
-    /** Registers a callback on data usage. */
-    DataUsageRequest registerUsageCallback(String callingPackage,
-            in DataUsageRequest request, in IUsageCallback callback);
-
-    /** Unregisters a callback on data usage. */
-    void unregisterUsageRequest(in DataUsageRequest request);
-
-    /** Get the uid stats information since boot */
-    long getUidStats(int uid, int type);
-
-    /** Get the iface stats information since boot */
-    long getIfaceStats(String iface, int type);
-
-    /** Get the total network stats information since boot */
-    long getTotalStats(int type);
-
-    /** Registers a network stats provider */
-    INetworkStatsProviderCallback registerNetworkStatsProvider(String tag,
-            in INetworkStatsProvider provider);
-
-    /** Mark given UID as being in foreground for stats purposes. */
-    void noteUidForeground(int uid, boolean uidForeground);
-
-    /** Advise persistence threshold; may be overridden internally. */
-    void advisePersistThreshold(long thresholdBytes);
-
-    /**
-     * Set the warning and limit to all registered custom network stats providers.
-     * Note that invocation of any interface will be sent to all providers.
-     */
-     void setStatsProviderWarningAndLimitAsync(String iface, long warning, long limit);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
deleted file mode 100644
index ab70be8..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-
-/** {@hide} */
-interface INetworkStatsSession {
-
-    /** Return device aggregated network layer usage summary for traffic that matches template. */
-    NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end);
-
-    /** Return network layer usage summary for traffic that matches template. */
-    @UnsupportedAppUsage
-    NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
-    /** Return historical network layer stats for traffic that matches template. */
-    @UnsupportedAppUsage
-    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
-    /**
-     * Return historical network layer stats for traffic that matches template, start and end
-     * timestamp.
-     */
-    NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);
-
-    /**
-     * Return network layer usage summary per UID for traffic that matches template.
-     *
-     * <p>The resulting {@code NetworkStats#getElapsedRealtime()} contains time delta between
-     * {@code start} and {@code end}.
-     *
-     * @param template - a predicate to filter netstats.
-     * @param start - start of the range, timestamp in milliseconds since the epoch.
-     * @param end - end of the range, timestamp in milliseconds since the epoch.
-     * @param includeTags - includes data usage tags if true.
-     */
-    @UnsupportedAppUsage
-    NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
-
-    /** Return network layer usage summary per UID for tagged traffic that matches template. */
-    NetworkStats getTaggedSummaryForAllUid(in NetworkTemplate template, long start, long end);
-
-    /** Return historical network layer stats for specific UID traffic that matches template. */
-    @UnsupportedAppUsage
-    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
-    /** Return historical network layer stats for specific UID traffic that matches template. */
-    NetworkStatsHistory getHistoryIntervalForUid(in NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end);
-
-    /** Return array of uids that have stats and are accessible to the calling user */
-    int[] getRelevantUids();
-
-    @UnsupportedAppUsage
-    void close();
-
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
deleted file mode 100644
index 14aa023..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/ITetheredInterfaceCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-oneway interface ITetheredInterfaceCallback {
-    void onAvailable(in String iface);
-    void onUnavailable();
-}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
deleted file mode 100644
index 10a22ac..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.annotation.NonNull;
-import android.annotation.StringDef;
-import android.content.res.Resources;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * This class represents a single algorithm that can be used by an {@link IpSecTransform}.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- * Internet Protocol</a>
- */
-public final class IpSecAlgorithm implements Parcelable {
-    private static final String TAG = "IpSecAlgorithm";
-
-    /**
-     * Null cipher.
-     *
-     * @hide
-     */
-    public static final String CRYPT_NULL = "ecb(cipher_null)";
-
-    /**
-     * AES-CBC Encryption/Ciphering Algorithm.
-     *
-     * <p>Valid lengths for this key are {128, 192, 256}.
-     */
-    public static final String CRYPT_AES_CBC = "cbc(aes)";
-
-    /**
-     * AES-CTR Encryption/Ciphering Algorithm.
-     *
-     * <p>Valid lengths for keying material are {160, 224, 288}.
-     *
-     * <p>As per <a href="https://tools.ietf.org/html/rfc3686#section-5.1">RFC3686 (Section
-     * 5.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
-     * nonce. RFC compliance requires that the nonce must be unique per security association.
-     *
-     * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
-     * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
-     * included in the returned algorithm set. The returned algorithm set will not change unless the
-     * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
-     * requested on an unsupported device.
-     *
-     * <p>@see {@link #getSupportedAlgorithms()}
-     */
-    // This algorithm may be available on devices released before Android 12, and is guaranteed
-    // to be available on devices first shipped with Android 12 or later.
-    public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
-
-    /**
-     * MD5 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
-     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
-     *
-     * <p>Keys for this algorithm must be 128 bits in length.
-     *
-     * <p>Valid truncation lengths are multiples of 8 bits from 96 to 128.
-     */
-    public static final String AUTH_HMAC_MD5 = "hmac(md5)";
-
-    /**
-     * SHA1 HMAC Authentication/Integrity Algorithm. <b>This algorithm is not recommended for use in
-     * new applications and is provided for legacy compatibility with 3gpp infrastructure.</b>
-     *
-     * <p>Keys for this algorithm must be 160 bits in length.
-     *
-     * <p>Valid truncation lengths are multiples of 8 bits from 96 to 160.
-     */
-    public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
-
-    /**
-     * SHA256 HMAC Authentication/Integrity Algorithm.
-     *
-     * <p>Keys for this algorithm must be 256 bits in length.
-     *
-     * <p>Valid truncation lengths are multiples of 8 bits from 96 to 256.
-     */
-    public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
-
-    /**
-     * SHA384 HMAC Authentication/Integrity Algorithm.
-     *
-     * <p>Keys for this algorithm must be 384 bits in length.
-     *
-     * <p>Valid truncation lengths are multiples of 8 bits from 192 to 384.
-     */
-    public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
-
-    /**
-     * SHA512 HMAC Authentication/Integrity Algorithm.
-     *
-     * <p>Keys for this algorithm must be 512 bits in length.
-     *
-     * <p>Valid truncation lengths are multiples of 8 bits from 256 to 512.
-     */
-    public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
-
-    /**
-     * AES-XCBC Authentication/Integrity Algorithm.
-     *
-     * <p>Keys for this algorithm must be 128 bits in length.
-     *
-     * <p>The only valid truncation length is 96 bits.
-     *
-     * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
-     * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
-     * included in the returned algorithm set. The returned algorithm set will not change unless the
-     * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
-     * requested on an unsupported device.
-     *
-     * <p>@see {@link #getSupportedAlgorithms()}
-     */
-    // This algorithm may be available on devices released before Android 12, and is guaranteed
-    // to be available on devices first shipped with Android 12 or later.
-    public static final String AUTH_AES_XCBC = "xcbc(aes)";
-
-    /**
-     * AES-CMAC Authentication/Integrity Algorithm.
-     *
-     * <p>Keys for this algorithm must be 128 bits in length.
-     *
-     * <p>The only valid truncation length is 96 bits.
-     *
-     * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
-     * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
-     * included in the returned algorithm set. The returned algorithm set will not change unless the
-     * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
-     * requested on an unsupported device.
-     *
-     * <p>@see {@link #getSupportedAlgorithms()}
-     */
-    // This algorithm may be available on devices released before Android 12, and is guaranteed
-    // to be available on devices first shipped with Android 12 or later.
-    public static final String AUTH_AES_CMAC = "cmac(aes)";
-
-    /**
-     * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
-     *
-     * <p>Valid lengths for keying material are {160, 224, 288}.
-     *
-     * <p>As per <a href="https://tools.ietf.org/html/rfc4106#section-8.1">RFC4106 (Section
-     * 8.1)</a>, keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit
-     * salt. RFC compliance requires that the salt must be unique per invocation with the same key.
-     *
-     * <p>Valid ICV (truncation) lengths are {64, 96, 128}.
-     */
-    public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
-
-    /**
-     * ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm.
-     *
-     * <p>Keys for this algorithm must be 288 bits in length.
-     *
-     * <p>As per <a href="https://tools.ietf.org/html/rfc7634#section-2">RFC7634 (Section 2)</a>,
-     * keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per
-     * security association.
-     *
-     * <p>The only valid ICV (truncation) length is 128 bits.
-     *
-     * <p>This algorithm may be available on the device. Caller MUST check if it is supported before
-     * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is
-     * included in the returned algorithm set. The returned algorithm set will not change unless the
-     * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is
-     * requested on an unsupported device.
-     *
-     * <p>@see {@link #getSupportedAlgorithms()}
-     */
-    // This algorithm may be available on devices released before Android 12, and is guaranteed
-    // to be available on devices first shipped with Android 12 or later.
-    public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
-
-    /** @hide */
-    @StringDef({
-        CRYPT_AES_CBC,
-        CRYPT_AES_CTR,
-        AUTH_HMAC_MD5,
-        AUTH_HMAC_SHA1,
-        AUTH_HMAC_SHA256,
-        AUTH_HMAC_SHA384,
-        AUTH_HMAC_SHA512,
-        AUTH_AES_XCBC,
-        AUTH_AES_CMAC,
-        AUTH_CRYPT_AES_GCM,
-        AUTH_CRYPT_CHACHA20_POLY1305
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AlgorithmName {}
-
-    /** @hide */
-    @VisibleForTesting
-    public static final Map<String, Integer> ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>();
-
-    private static final int SDK_VERSION_ZERO = 0;
-
-    static {
-        ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO);
-
-        ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S);
-        ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S);
-    }
-
-    private static final Set<String> ENABLED_ALGOS =
-            Collections.unmodifiableSet(loadAlgos(Resources.getSystem()));
-
-    private final String mName;
-    private final byte[] mKey;
-    private final int mTruncLenBits;
-
-    /**
-     * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
-     * defined as constants in this class.
-     *
-     * <p>For algorithms that produce an integrity check value, the truncation length is a required
-     * parameter. See {@link #IpSecAlgorithm(String algorithm, byte[] key, int truncLenBits)}
-     *
-     * @param algorithm name of the algorithm.
-     * @param key key padded to a multiple of 8 bits.
-     * @throws IllegalArgumentException if algorithm or key length is invalid.
-     */
-    public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) {
-        this(algorithm, key, 0);
-    }
-
-    /**
-     * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are
-     * defined as constants in this class.
-     *
-     * <p>This constructor only supports algorithms that use a truncation length. i.e.
-     * Authentication and Authenticated Encryption algorithms.
-     *
-     * @param algorithm name of the algorithm.
-     * @param key key padded to a multiple of 8 bits.
-     * @param truncLenBits number of bits of output hash to use.
-     * @throws IllegalArgumentException if algorithm, key length or truncation length is invalid.
-     */
-    public IpSecAlgorithm(
-            @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) {
-        mName = algorithm;
-        mKey = key.clone();
-        mTruncLenBits = truncLenBits;
-        checkValidOrThrow(mName, mKey.length * 8, mTruncLenBits);
-    }
-
-    /** Get the algorithm name */
-    @NonNull
-    public String getName() {
-        return mName;
-    }
-
-    /** Get the key for this algorithm */
-    @NonNull
-    public byte[] getKey() {
-        return mKey.clone();
-    }
-
-    /** Get the truncation length of this algorithm, in bits */
-    public int getTruncationLengthBits() {
-        return mTruncLenBits;
-    }
-
-    /** Parcelable Implementation */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Write to parcel */
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(mName);
-        out.writeByteArray(mKey);
-        out.writeInt(mTruncLenBits);
-    }
-
-    /** Parcelable Creator */
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecAlgorithm> CREATOR =
-            new Parcelable.Creator<IpSecAlgorithm>() {
-                public IpSecAlgorithm createFromParcel(Parcel in) {
-                    final String name = in.readString();
-                    final byte[] key = in.createByteArray();
-                    final int truncLenBits = in.readInt();
-
-                    return new IpSecAlgorithm(name, key, truncLenBits);
-                }
-
-                public IpSecAlgorithm[] newArray(int size) {
-                    return new IpSecAlgorithm[size];
-                }
-            };
-
-    /**
-     * Returns supported IPsec algorithms for the current device.
-     *
-     * <p>Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is
-     * supported before using it.
-     */
-    @NonNull
-    public static Set<String> getSupportedAlgorithms() {
-        return ENABLED_ALGOS;
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public static Set<String> loadAlgos(Resources systemResources) {
-        final Set<String> enabledAlgos = new HashSet<>();
-
-        // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
-        // the resource are not allowed.
-        final String[] resourceAlgos = systemResources.getStringArray(
-                android.R.array.config_optionalIpSecAlgorithms);
-        for (String str : resourceAlgos) {
-            if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
-                // This error should be caught by CTS and never be thrown to API callers
-                throw new IllegalArgumentException("Invalid or repeated algorithm " + str);
-            }
-        }
-
-        for (Entry<String, Integer> entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) {
-            if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= entry.getValue()) {
-                enabledAlgos.add(entry.getKey());
-            }
-        }
-
-        return enabledAlgos;
-    }
-
-    private static void checkValidOrThrow(String name, int keyLen, int truncLen) {
-        final boolean isValidLen;
-        final boolean isValidTruncLen;
-
-        if (!getSupportedAlgorithms().contains(name)) {
-            throw new IllegalArgumentException("Unsupported algorithm: " + name);
-        }
-
-        switch (name) {
-            case CRYPT_AES_CBC:
-                isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256;
-                isValidTruncLen = true;
-                break;
-            case CRYPT_AES_CTR:
-                // The keying material for AES-CTR is a key plus a 32-bit salt
-                isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
-                isValidTruncLen = true;
-                break;
-            case AUTH_HMAC_MD5:
-                isValidLen = keyLen == 128;
-                isValidTruncLen = truncLen >= 96 && truncLen <= 128;
-                break;
-            case AUTH_HMAC_SHA1:
-                isValidLen = keyLen == 160;
-                isValidTruncLen = truncLen >= 96 && truncLen <= 160;
-                break;
-            case AUTH_HMAC_SHA256:
-                isValidLen = keyLen == 256;
-                isValidTruncLen = truncLen >= 96 && truncLen <= 256;
-                break;
-            case AUTH_HMAC_SHA384:
-                isValidLen = keyLen == 384;
-                isValidTruncLen = truncLen >= 192 && truncLen <= 384;
-                break;
-            case AUTH_HMAC_SHA512:
-                isValidLen = keyLen == 512;
-                isValidTruncLen = truncLen >= 256 && truncLen <= 512;
-                break;
-            case AUTH_AES_XCBC:
-                isValidLen = keyLen == 128;
-                isValidTruncLen = truncLen == 96;
-                break;
-            case AUTH_AES_CMAC:
-                isValidLen = keyLen == 128;
-                isValidTruncLen = truncLen == 96;
-                break;
-            case AUTH_CRYPT_AES_GCM:
-                // The keying material for GCM is a key plus a 32-bit salt
-                isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32;
-                isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128;
-                break;
-            case AUTH_CRYPT_CHACHA20_POLY1305:
-                // The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt
-                isValidLen = keyLen == 256 + 32;
-                isValidTruncLen = truncLen == 128;
-                break;
-            default:
-                // Should never hit here.
-                throw new IllegalArgumentException("Couldn't find an algorithm: " + name);
-        }
-
-        if (!isValidLen) {
-            throw new IllegalArgumentException("Invalid key material keyLength: " + keyLen);
-        }
-        if (!isValidTruncLen) {
-            throw new IllegalArgumentException("Invalid truncation keyLength: " + truncLen);
-        }
-    }
-
-    /** @hide */
-    public boolean isAuthentication() {
-        switch (getName()) {
-            // Fallthrough
-            case AUTH_HMAC_MD5:
-            case AUTH_HMAC_SHA1:
-            case AUTH_HMAC_SHA256:
-            case AUTH_HMAC_SHA384:
-            case AUTH_HMAC_SHA512:
-            case AUTH_AES_XCBC:
-            case AUTH_AES_CMAC:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /** @hide */
-    public boolean isEncryption() {
-        switch (getName()) {
-            case CRYPT_AES_CBC: // fallthrough
-            case CRYPT_AES_CTR:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /** @hide */
-    public boolean isAead() {
-        switch (getName()) {
-            case AUTH_CRYPT_AES_GCM: // fallthrough
-            case AUTH_CRYPT_CHACHA20_POLY1305:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    @Override
-    @NonNull
-    public String toString() {
-        return new StringBuilder()
-                .append("{mName=")
-                .append(mName)
-                .append(", mTruncLenBits=")
-                .append(mTruncLenBits)
-                .append("}")
-                .toString();
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
-        if (lhs == null || rhs == null) return (lhs == rhs);
-        return (lhs.mName.equals(rhs.mName)
-                && Arrays.equals(lhs.mKey, rhs.mKey)
-                && lhs.mTruncLenBits == rhs.mTruncLenBits);
-    }
-};
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl
deleted file mode 100644
index eaefca7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-parcelable IpSecConfig;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
deleted file mode 100644
index 575c5ed..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * This class encapsulates all the configuration parameters needed to create IPsec transforms and
- * policies.
- *
- * @hide
- */
-public final class IpSecConfig implements Parcelable {
-    private static final String TAG = "IpSecConfig";
-
-    // MODE_TRANSPORT or MODE_TUNNEL
-    private int mMode = IpSecTransform.MODE_TRANSPORT;
-
-    // Preventing this from being null simplifies Java->Native binder
-    private String mSourceAddress = "";
-
-    // Preventing this from being null simplifies Java->Native binder
-    private String mDestinationAddress = "";
-
-    // The underlying Network that represents the "gateway" Network
-    // for outbound packets. It may also be used to select packets.
-    private Network mNetwork;
-
-    // Minimum requirements for identifying a transform
-    // SPI identifying the IPsec SA in packet processing
-    // and a destination IP address
-    private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
-
-    // Encryption Algorithm
-    private IpSecAlgorithm mEncryption;
-
-    // Authentication Algorithm
-    private IpSecAlgorithm mAuthentication;
-
-    // Authenticated Encryption Algorithm
-    private IpSecAlgorithm mAuthenticatedEncryption;
-
-    // For tunnel mode IPv4 UDP Encapsulation
-    // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
-    private int mEncapType = IpSecTransform.ENCAP_NONE;
-    private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID;
-    private int mEncapRemotePort;
-
-    // An interval, in seconds between the NattKeepalive packets
-    private int mNattKeepaliveInterval;
-
-    // XFRM mark and mask; defaults to 0 (no mark/mask)
-    private int mMarkValue;
-    private int mMarkMask;
-
-    // XFRM interface id
-    private int mXfrmInterfaceId;
-
-    /** Set the mode for this IPsec transform */
-    public void setMode(int mode) {
-        mMode = mode;
-    }
-
-    /** Set the source IP addres for this IPsec transform */
-    public void setSourceAddress(String sourceAddress) {
-        mSourceAddress = sourceAddress;
-    }
-
-    /** Set the destination IP address for this IPsec transform */
-    public void setDestinationAddress(String destinationAddress) {
-        mDestinationAddress = destinationAddress;
-    }
-
-    /** Set the SPI by resource ID */
-    public void setSpiResourceId(int resourceId) {
-        mSpiResourceId = resourceId;
-    }
-
-    /** Set the encryption algorithm */
-    public void setEncryption(IpSecAlgorithm encryption) {
-        mEncryption = encryption;
-    }
-
-    /** Set the authentication algorithm */
-    public void setAuthentication(IpSecAlgorithm authentication) {
-        mAuthentication = authentication;
-    }
-
-    /** Set the authenticated encryption algorithm */
-    public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) {
-        mAuthenticatedEncryption = authenticatedEncryption;
-    }
-
-    /** Set the underlying network that will carry traffic for this transform */
-    public void setNetwork(Network network) {
-        mNetwork = network;
-    }
-
-    public void setEncapType(int encapType) {
-        mEncapType = encapType;
-    }
-
-    public void setEncapSocketResourceId(int resourceId) {
-        mEncapSocketResourceId = resourceId;
-    }
-
-    public void setEncapRemotePort(int port) {
-        mEncapRemotePort = port;
-    }
-
-    public void setNattKeepaliveInterval(int interval) {
-        mNattKeepaliveInterval = interval;
-    }
-
-    /**
-     * Sets the mark value
-     *
-     * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
-     * ignored.
-     */
-    public void setMarkValue(int mark) {
-        mMarkValue = mark;
-    }
-
-    /**
-     * Sets the mark mask
-     *
-     * <p>Internal (System server) use only. Marks passed in by users will be overwritten or
-     * ignored.
-     */
-    public void setMarkMask(int mask) {
-        mMarkMask = mask;
-    }
-
-    public void setXfrmInterfaceId(int xfrmInterfaceId) {
-        mXfrmInterfaceId = xfrmInterfaceId;
-    }
-
-    // Transport or Tunnel
-    public int getMode() {
-        return mMode;
-    }
-
-    public String getSourceAddress() {
-        return mSourceAddress;
-    }
-
-    public int getSpiResourceId() {
-        return mSpiResourceId;
-    }
-
-    public String getDestinationAddress() {
-        return mDestinationAddress;
-    }
-
-    public IpSecAlgorithm getEncryption() {
-        return mEncryption;
-    }
-
-    public IpSecAlgorithm getAuthentication() {
-        return mAuthentication;
-    }
-
-    public IpSecAlgorithm getAuthenticatedEncryption() {
-        return mAuthenticatedEncryption;
-    }
-
-    public Network getNetwork() {
-        return mNetwork;
-    }
-
-    public int getEncapType() {
-        return mEncapType;
-    }
-
-    public int getEncapSocketResourceId() {
-        return mEncapSocketResourceId;
-    }
-
-    public int getEncapRemotePort() {
-        return mEncapRemotePort;
-    }
-
-    public int getNattKeepaliveInterval() {
-        return mNattKeepaliveInterval;
-    }
-
-    public int getMarkValue() {
-        return mMarkValue;
-    }
-
-    public int getMarkMask() {
-        return mMarkMask;
-    }
-
-    public int getXfrmInterfaceId() {
-        return mXfrmInterfaceId;
-    }
-
-    // Parcelable Methods
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mMode);
-        out.writeString(mSourceAddress);
-        out.writeString(mDestinationAddress);
-        out.writeParcelable(mNetwork, flags);
-        out.writeInt(mSpiResourceId);
-        out.writeParcelable(mEncryption, flags);
-        out.writeParcelable(mAuthentication, flags);
-        out.writeParcelable(mAuthenticatedEncryption, flags);
-        out.writeInt(mEncapType);
-        out.writeInt(mEncapSocketResourceId);
-        out.writeInt(mEncapRemotePort);
-        out.writeInt(mNattKeepaliveInterval);
-        out.writeInt(mMarkValue);
-        out.writeInt(mMarkMask);
-        out.writeInt(mXfrmInterfaceId);
-    }
-
-    @VisibleForTesting
-    public IpSecConfig() {}
-
-    /** Copy constructor */
-    @VisibleForTesting
-    public IpSecConfig(IpSecConfig c) {
-        mMode = c.mMode;
-        mSourceAddress = c.mSourceAddress;
-        mDestinationAddress = c.mDestinationAddress;
-        mNetwork = c.mNetwork;
-        mSpiResourceId = c.mSpiResourceId;
-        mEncryption = c.mEncryption;
-        mAuthentication = c.mAuthentication;
-        mAuthenticatedEncryption = c.mAuthenticatedEncryption;
-        mEncapType = c.mEncapType;
-        mEncapSocketResourceId = c.mEncapSocketResourceId;
-        mEncapRemotePort = c.mEncapRemotePort;
-        mNattKeepaliveInterval = c.mNattKeepaliveInterval;
-        mMarkValue = c.mMarkValue;
-        mMarkMask = c.mMarkMask;
-        mXfrmInterfaceId = c.mXfrmInterfaceId;
-    }
-
-    private IpSecConfig(Parcel in) {
-        mMode = in.readInt();
-        mSourceAddress = in.readString();
-        mDestinationAddress = in.readString();
-        mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
-        mSpiResourceId = in.readInt();
-        mEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mAuthentication =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mAuthenticatedEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
-        mEncapType = in.readInt();
-        mEncapSocketResourceId = in.readInt();
-        mEncapRemotePort = in.readInt();
-        mNattKeepaliveInterval = in.readInt();
-        mMarkValue = in.readInt();
-        mMarkMask = in.readInt();
-        mXfrmInterfaceId = in.readInt();
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder strBuilder = new StringBuilder();
-        strBuilder
-                .append("{mMode=")
-                .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
-                .append(", mSourceAddress=")
-                .append(mSourceAddress)
-                .append(", mDestinationAddress=")
-                .append(mDestinationAddress)
-                .append(", mNetwork=")
-                .append(mNetwork)
-                .append(", mEncapType=")
-                .append(mEncapType)
-                .append(", mEncapSocketResourceId=")
-                .append(mEncapSocketResourceId)
-                .append(", mEncapRemotePort=")
-                .append(mEncapRemotePort)
-                .append(", mNattKeepaliveInterval=")
-                .append(mNattKeepaliveInterval)
-                .append("{mSpiResourceId=")
-                .append(mSpiResourceId)
-                .append(", mEncryption=")
-                .append(mEncryption)
-                .append(", mAuthentication=")
-                .append(mAuthentication)
-                .append(", mAuthenticatedEncryption=")
-                .append(mAuthenticatedEncryption)
-                .append(", mMarkValue=")
-                .append(mMarkValue)
-                .append(", mMarkMask=")
-                .append(mMarkMask)
-                .append(", mXfrmInterfaceId=")
-                .append(mXfrmInterfaceId)
-                .append("}");
-
-        return strBuilder.toString();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecConfig> CREATOR =
-            new Parcelable.Creator<IpSecConfig>() {
-                public IpSecConfig createFromParcel(Parcel in) {
-                    return new IpSecConfig(in);
-                }
-
-                public IpSecConfig[] newArray(int size) {
-                    return new IpSecConfig[size];
-                }
-            };
-
-    @Override
-    public boolean equals(@Nullable Object other) {
-        if (!(other instanceof IpSecConfig)) return false;
-        final IpSecConfig rhs = (IpSecConfig) other;
-        return (mMode == rhs.mMode
-                && mSourceAddress.equals(rhs.mSourceAddress)
-                && mDestinationAddress.equals(rhs.mDestinationAddress)
-                && ((mNetwork != null && mNetwork.equals(rhs.mNetwork))
-                        || (mNetwork == rhs.mNetwork))
-                && mEncapType == rhs.mEncapType
-                && mEncapSocketResourceId == rhs.mEncapSocketResourceId
-                && mEncapRemotePort == rhs.mEncapRemotePort
-                && mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
-                && mSpiResourceId == rhs.mSpiResourceId
-                && IpSecAlgorithm.equals(mEncryption, rhs.mEncryption)
-                && IpSecAlgorithm.equals(mAuthenticatedEncryption, rhs.mAuthenticatedEncryption)
-                && IpSecAlgorithm.equals(mAuthentication, rhs.mAuthentication)
-                && mMarkValue == rhs.mMarkValue
-                && mMarkMask == rhs.mMarkMask
-                && mXfrmInterfaceId == rhs.mXfrmInterfaceId);
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
deleted file mode 100644
index 9cb0947..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.annotation.TestApi;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.util.AndroidException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import dalvik.system.CloseGuard;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-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
- * confidentiality (encryption) and integrity (authentication) to IP traffic.
- *
- * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
- * transport mode security associations and apply them to individual sockets. Applications looking
- * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- *     Internet Protocol</a>
- */
-@SystemService(Context.IPSEC_SERVICE)
-public class IpSecManager {
-    private static final String TAG = "IpSecManager";
-
-    /**
-     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
-     * towards the host.
-     *
-     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
-     */
-    public static final int DIRECTION_IN = 0;
-
-    /**
-     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
-     * away from the host.
-     *
-     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
-     */
-    public static final int DIRECTION_OUT = 1;
-
-    /**
-     * Used when applying a transform to direct traffic through an {@link IpSecTransform} for
-     * forwarding between interfaces.
-     *
-     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static final int DIRECTION_FWD = 2;
-
-    /** @hide */
-    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface PolicyDirection {}
-
-    /**
-     * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
-     *
-     * <p>No IPsec packet may contain an SPI of 0.
-     *
-     * @hide
-     */
-    @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
-
-    /** @hide */
-    public interface Status {
-        int OK = 0;
-        int RESOURCE_UNAVAILABLE = 1;
-        int SPI_UNAVAILABLE = 2;
-    }
-
-    /** @hide */
-    public static final int INVALID_RESOURCE_ID = -1;
-
-    /**
-     * Thrown to indicate that a requested SPI is in use.
-     *
-     * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
-     * one device. If this error is encountered, a new SPI is required before a transform may be
-     * created. This error can be avoided by calling {@link
-     * IpSecManager#allocateSecurityParameterIndex}.
-     */
-    public static final class SpiUnavailableException extends AndroidException {
-        private final int mSpi;
-
-        /**
-         * Construct an exception indicating that a transform with the given SPI is already in use
-         * or otherwise unavailable.
-         *
-         * @param msg description indicating the colliding SPI
-         * @param spi the SPI that could not be used due to a collision
-         */
-        SpiUnavailableException(String msg, int spi) {
-            super(msg + " (spi: " + spi + ")");
-            mSpi = spi;
-        }
-
-        /** Get the SPI that caused a collision. */
-        public int getSpi() {
-            return mSpi;
-        }
-    }
-
-    /**
-     * Thrown to indicate that an IPsec resource is unavailable.
-     *
-     * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link
-     * IpSecTransform}, or other system resources. If this exception is thrown, users should release
-     * allocated objects of the type requested.
-     */
-    public static final class ResourceUnavailableException extends AndroidException {
-
-        ResourceUnavailableException(String msg) {
-            super(msg);
-        }
-    }
-
-    private final Context mContext;
-    private final IIpSecService mService;
-
-    /**
-     * This class represents a reserved SPI.
-     *
-     * <p>Objects of this type are used to track reserved security parameter indices. They can be
-     * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released
-     * by calling {@link #close()} when they are no longer needed.
-     */
-    public static final class SecurityParameterIndex implements AutoCloseable {
-        private final IIpSecService mService;
-        private final InetAddress mDestinationAddress;
-        private final CloseGuard mCloseGuard = CloseGuard.get();
-        private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
-        private int mResourceId = INVALID_RESOURCE_ID;
-
-        /** Get the underlying SPI held by this object. */
-        public int getSpi() {
-            return mSpi;
-        }
-
-        /**
-         * Release an SPI that was previously reserved.
-         *
-         * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
-         * applied to an IpSecTransform, it will become unusable for future transforms but should
-         * still be closed to ensure system resources are released.
-         */
-        @Override
-        public void close() {
-            try {
-                mService.releaseSecurityParameterIndex(mResourceId);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            } catch (Exception e) {
-                // On close we swallow all random exceptions since failure to close is not
-                // actionable by the user.
-                Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
-            } finally {
-                mResourceId = INVALID_RESOURCE_ID;
-                mCloseGuard.close();
-            }
-        }
-
-        /** Check that the SPI was closed properly. */
-        @Override
-        protected void finalize() throws Throwable {
-            if (mCloseGuard != null) {
-                mCloseGuard.warnIfOpen();
-            }
-
-            close();
-        }
-
-        private SecurityParameterIndex(
-                @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
-                throws ResourceUnavailableException, SpiUnavailableException {
-            mService = service;
-            mDestinationAddress = destinationAddress;
-            try {
-                IpSecSpiResponse result =
-                        mService.allocateSecurityParameterIndex(
-                                destinationAddress.getHostAddress(), spi, new Binder());
-
-                if (result == null) {
-                    throw new NullPointerException("Received null response from IpSecService");
-                }
-
-                int status = result.status;
-                switch (status) {
-                    case Status.OK:
-                        break;
-                    case Status.RESOURCE_UNAVAILABLE:
-                        throw new ResourceUnavailableException(
-                                "No more SPIs may be allocated by this requester.");
-                    case Status.SPI_UNAVAILABLE:
-                        throw new SpiUnavailableException("Requested SPI is unavailable", spi);
-                    default:
-                        throw new RuntimeException(
-                                "Unknown status returned by IpSecService: " + status);
-                }
-                mSpi = result.spi;
-                mResourceId = result.resourceId;
-
-                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
-                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
-                }
-
-                if (mResourceId == INVALID_RESOURCE_ID) {
-                    throw new RuntimeException(
-                            "Invalid Resource ID returned by IpSecService: " + status);
-                }
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            mCloseGuard.open("open");
-        }
-
-        /** @hide */
-        @VisibleForTesting
-        public int getResourceId() {
-            return mResourceId;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                .append("SecurityParameterIndex{spi=")
-                .append(mSpi)
-                .append(",resourceId=")
-                .append(mResourceId)
-                .append("}")
-                .toString();
-        }
-    }
-
-    /**
-     * Reserve a random SPI for traffic bound to or from the specified destination address.
-     *
-     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
-     * SecurityParameterIndex#close()}.
-     *
-     * @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 ResourceUnavailableException indicating that too many SPIs are
-     *     currently allocated for this user
-     */
-    @NonNull
-    public SecurityParameterIndex allocateSecurityParameterIndex(
-                @NonNull InetAddress destinationAddress) throws ResourceUnavailableException {
-        try {
-            return new SecurityParameterIndex(
-                    mService,
-                    destinationAddress,
-                    IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
-        } catch (ServiceSpecificException e) {
-            throw rethrowUncheckedExceptionFromServiceSpecificException(e);
-        } catch (SpiUnavailableException unlikely) {
-            // Because this function allocates a totally random SPI, it really shouldn't ever
-            // fail to allocate an SPI; we simply need this because the exception is checked.
-            throw new ResourceUnavailableException("No SPIs available");
-        }
-    }
-
-    /**
-     * Reserve the requested SPI for traffic bound to or from the specified destination address.
-     *
-     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
-     * SecurityParameterIndex#close()}.
-     *
-     * @param destinationAddress the destination address for traffic bearing the requested SPI.
-     *     For inbound traffic, the destination should be an address currently assigned on-device.
-     * @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 ResourceUnavailableException indicating that too many SPIs are
-     *     currently allocated for this user
-     * @throws SpiUnavailableException indicating that the requested SPI could not be
-     *     reserved
-     */
-    @NonNull
-    public SecurityParameterIndex allocateSecurityParameterIndex(
-            @NonNull InetAddress destinationAddress, int requestedSpi)
-            throws SpiUnavailableException, ResourceUnavailableException {
-        if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
-            throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
-        }
-        try {
-            return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
-        } catch (ServiceSpecificException e) {
-            throw rethrowUncheckedExceptionFromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Apply an IPsec transform to a stream socket.
-     *
-     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
-     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
-     * unprotected traffic can resume on that socket.
-     *
-     * <p>For security reasons, the destination address of any traffic on the socket must match the
-     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
-     * other IP address will result in an IOException. In addition, reads and writes on the socket
-     * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
-     *
-     * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
-     * applied transform before completion of graceful shutdown may result in the shutdown sequence
-     * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
-     * prior to deactivating the applied transform. Socket closure may be performed asynchronously
-     * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
-     * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
-     * sufficient to ensure shutdown.
-     *
-     * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
-     * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
-     * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
-     * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
-     *
-     * <h4>Rekey Procedure</h4>
-     *
-     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
-     * will be removed and the new transform will take effect immediately, sending all traffic on
-     * the new transform; however, when applying a transform in the inbound direction, traffic
-     * on the old transform will continue to be decrypted and delivered until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
-     * procedures where both transforms are valid until both endpoints are using the new transform
-     * and all in-flight packets have been received.
-     *
-     * @param socket a stream socket
-     * @param direction the direction in which the transform should be applied
-     * @param transform a transport mode {@code IpSecTransform}
-     * @throws IOException indicating that the transform could not be applied
-     */
-    public void applyTransportModeTransform(@NonNull Socket socket,
-            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
-        // Ensure creation of FD. See b/77548890 for more details.
-        socket.getSoLinger();
-
-        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
-    }
-
-    /**
-     * Apply an IPsec transform to a datagram socket.
-     *
-     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
-     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
-     * unprotected traffic can resume on that socket.
-     *
-     * <p>For security reasons, the destination address of any traffic on the socket must match the
-     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
-     * other IP address will result in an IOException. In addition, reads and writes on the socket
-     * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
-     *
-     * <h4>Rekey Procedure</h4>
-     *
-     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
-     * will be removed and the new transform will take effect immediately, sending all traffic on
-     * the new transform; however, when applying a transform in the inbound direction, traffic
-     * on the old transform will continue to be decrypted and delivered until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
-     * procedures where both transforms are valid until both endpoints are using the new transform
-     * and all in-flight packets have been received.
-     *
-     * @param socket a datagram socket
-     * @param direction the direction in which the transform should be applied
-     * @param transform a transport mode {@code IpSecTransform}
-     * @throws IOException indicating that the transform could not be applied
-     */
-    public void applyTransportModeTransform(@NonNull DatagramSocket socket,
-            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
-        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
-    }
-
-    /**
-     * Apply an IPsec transform to a socket.
-     *
-     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
-     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
-     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
-     * unprotected traffic can resume on that socket.
-     *
-     * <p>For security reasons, the destination address of any traffic on the socket must match the
-     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
-     * other IP address will result in an IOException. In addition, reads and writes on the socket
-     * will throw IOException if the user deactivates the transform (by calling {@link
-     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
-     *
-     * <p>Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an
-     * applied transform before completion of graceful shutdown may result in the shutdown sequence
-     * failing to complete. As such, applications requiring graceful shutdown MUST close the socket
-     * prior to deactivating the applied transform. Socket closure may be performed asynchronously
-     * (in batches), so the returning of a close function does not guarantee shutdown of a socket.
-     * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is
-     * sufficient to ensure shutdown.
-     *
-     * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}),
-     * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST]
-     * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the
-     * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped.
-     *
-     * <h4>Rekey Procedure</h4>
-     *
-     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
-     * will be removed and the new transform will take effect immediately, sending all traffic on
-     * the new transform; however, when applying a transform in the inbound direction, traffic
-     * on the old transform will continue to be decrypted and delivered until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
-     * procedures where both transforms are valid until both endpoints are using the new transform
-     * and all in-flight packets have been received.
-     *
-     * @param socket a socket file descriptor
-     * @param direction the direction in which the transform should be applied
-     * @param transform a transport mode {@code IpSecTransform}
-     * @throws IOException indicating that the transform could not be applied
-     */
-    public void applyTransportModeTransform(@NonNull FileDescriptor socket,
-            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
-        // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
-        // constructor takes control and closes the user's FD when we exit the method.
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Remove an IPsec transform from a stream socket.
-     *
-     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
-     * socket allows the socket to be reused for communication in the clear.
-     *
-     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
-     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
-     * is called.
-     *
-     * @param socket a socket that previously had a transform applied to it
-     * @throws IOException indicating that the transform could not be removed from the socket
-     */
-    public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException {
-        // Ensure creation of FD. See b/77548890 for more details.
-        socket.getSoLinger();
-
-        removeTransportModeTransforms(socket.getFileDescriptor$());
-    }
-
-    /**
-     * Remove an IPsec transform from a datagram socket.
-     *
-     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
-     * socket allows the socket to be reused for communication in the clear.
-     *
-     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
-     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
-     * is called.
-     *
-     * @param socket a socket that previously had a transform applied to it
-     * @throws IOException indicating that the transform could not be removed from the socket
-     */
-    public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException {
-        removeTransportModeTransforms(socket.getFileDescriptor$());
-    }
-
-    /**
-     * Remove an IPsec transform from a socket.
-     *
-     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
-     * socket allows the socket to be reused for communication in the clear.
-     *
-     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
-     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
-     * is called.
-     *
-     * @param socket a socket that previously had a transform applied to it
-     * @throws IOException indicating that the transform could not be removed from the socket
-     */
-    public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException {
-        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
-            mService.removeTransportModeTransforms(pfd);
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
-     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
-     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
-     * lost, all traffic will drop.
-     *
-     * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
-     *
-     * @param net a network that currently has transform applied to it.
-     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
-     *     network
-     * @hide
-     */
-    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
-
-    /**
-     * This class provides access to a UDP encapsulation Socket.
-     *
-     * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
-     * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link
-     * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the
-     * caller. The caller should not close the {@code FileDescriptor} returned by {@link
-     * #getFileDescriptor}, but should use {@link #close} instead.
-     *
-     * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic
-     * of the next user who binds to that port. To prevent this scenario, these sockets are held
-     * open by the system so that they may only be closed by calling {@link #close} or when the user
-     * process exits.
-     */
-    public static final class UdpEncapsulationSocket implements AutoCloseable {
-        private final ParcelFileDescriptor mPfd;
-        private final IIpSecService mService;
-        private int mResourceId = INVALID_RESOURCE_ID;
-        private final int mPort;
-        private final CloseGuard mCloseGuard = CloseGuard.get();
-
-        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
-                throws ResourceUnavailableException, IOException {
-            mService = service;
-            try {
-                IpSecUdpEncapResponse result =
-                        mService.openUdpEncapsulationSocket(port, new Binder());
-                switch (result.status) {
-                    case Status.OK:
-                        break;
-                    case Status.RESOURCE_UNAVAILABLE:
-                        throw new ResourceUnavailableException(
-                                "No more Sockets may be allocated by this requester.");
-                    default:
-                        throw new RuntimeException(
-                                "Unknown status returned by IpSecService: " + result.status);
-                }
-                mResourceId = result.resourceId;
-                mPort = result.port;
-                mPfd = result.fileDescriptor;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            mCloseGuard.open("constructor");
-        }
-
-        /** Get the encapsulation socket's file descriptor. */
-        public FileDescriptor getFileDescriptor() {
-            if (mPfd == null) {
-                return null;
-            }
-            return mPfd.getFileDescriptor();
-        }
-
-        /** Get the bound port of the wrapped socket. */
-        public int getPort() {
-            return mPort;
-        }
-
-        /**
-         * Close this socket.
-         *
-         * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
-         * resource limits, and forgetting to close them eventually will result in {@link
-         * ResourceUnavailableException} being thrown.
-         */
-        @Override
-        public void close() throws IOException {
-            try {
-                mService.closeUdpEncapsulationSocket(mResourceId);
-                mResourceId = INVALID_RESOURCE_ID;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            } catch (Exception e) {
-                // On close we swallow all random exceptions since failure to close is not
-                // actionable by the user.
-                Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
-            } finally {
-                mResourceId = INVALID_RESOURCE_ID;
-                mCloseGuard.close();
-            }
-
-            try {
-                mPfd.close();
-            } catch (IOException e) {
-                Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
-                throw e;
-            }
-        }
-
-        /** Check that the socket was closed properly. */
-        @Override
-        protected void finalize() throws Throwable {
-            if (mCloseGuard != null) {
-                mCloseGuard.warnIfOpen();
-            }
-            close();
-        }
-
-        /** @hide */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getResourceId() {
-            return mResourceId;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                .append("UdpEncapsulationSocket{port=")
-                .append(mPort)
-                .append(",resourceId=")
-                .append(mResourceId)
-                .append("}")
-                .toString();
-        }
-    };
-
-    /**
-     * Open a socket for UDP encapsulation and bind to the given port.
-     *
-     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
-     *
-     * @param port a local UDP port
-     * @return a socket that is bound to the given port
-     * @throws IOException indicating that the socket could not be opened or bound
-     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
-     */
-    // Returning a socket in this fashion that has been created and bound by the system
-    // is the only safe way to ensure that a socket is both accessible to the user and
-    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
-    // the port, which could potentially impact the traffic of the next user who binds to that
-    // socket.
-    @NonNull
-    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
-            throws IOException, ResourceUnavailableException {
-        /*
-         * Most range checking is done in the service, but this version of the constructor expects
-         * a valid port number, and zero cannot be checked after being passed to the service.
-         */
-        if (port == 0) {
-            throw new IllegalArgumentException("Specified port must be a valid port number!");
-        }
-        try {
-            return new UdpEncapsulationSocket(mService, port);
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Open a socket for UDP encapsulation.
-     *
-     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
-     *
-     * <p>The local port of the returned socket can be obtained by calling {@link
-     * UdpEncapsulationSocket#getPort()}.
-     *
-     * @return a socket that is bound to a local port
-     * @throws IOException indicating that the socket could not be opened or bound
-     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
-     */
-    // Returning a socket in this fashion that has been created and bound by the system
-    // is the only safe way to ensure that a socket is both accessible to the user and
-    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
-    // the port, which could potentially impact the traffic of the next user who binds to that
-    // socket.
-    @NonNull
-    public UdpEncapsulationSocket openUdpEncapsulationSocket()
-            throws IOException, ResourceUnavailableException {
-        try {
-            return new UdpEncapsulationSocket(mService, 0);
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * This class represents an IpSecTunnelInterface
-     *
-     * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
-     * local endpoints for IPsec tunnels.
-     *
-     * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
-     * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
-     * cannot be used in standalone mode within Android, the higher layers may use the tunnel
-     * to create Network objects which are accessible to the Android system.
-     * @hide
-     */
-    @SystemApi
-    public static final class IpSecTunnelInterface implements AutoCloseable {
-        private final String mOpPackageName;
-        private final IIpSecService mService;
-        private final InetAddress mRemoteAddress;
-        private final InetAddress mLocalAddress;
-        private final Network mUnderlyingNetwork;
-        private final CloseGuard mCloseGuard = CloseGuard.get();
-        private String mInterfaceName;
-        private int mResourceId = INVALID_RESOURCE_ID;
-
-        /** Get the underlying SPI held by this object. */
-        @NonNull
-        public String getInterfaceName() {
-            return mInterfaceName;
-        }
-
-        /**
-         * Add an address to the IpSecTunnelInterface
-         *
-         * <p>Add an address which may be used as the local inner address for
-         * tunneled traffic.
-         *
-         * @param address the local address for traffic inside the tunnel
-         * @param prefixLen length of the InetAddress prefix
-         * @hide
-         */
-        @SystemApi
-        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-        public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
-            try {
-                mService.addAddressToTunnelInterface(
-                        mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
-            } catch (ServiceSpecificException e) {
-                throw rethrowCheckedExceptionFromServiceSpecificException(e);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-
-        /**
-         * Remove an address from the IpSecTunnelInterface
-         *
-         * <p>Remove an address which was previously added to the IpSecTunnelInterface
-         *
-         * @param address to be removed
-         * @param prefixLen length of the InetAddress prefix
-         * @hide
-         */
-        @SystemApi
-        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-        public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException {
-            try {
-                mService.removeAddressFromTunnelInterface(
-                        mResourceId, new LinkAddress(address, prefixLen), mOpPackageName);
-            } catch (ServiceSpecificException e) {
-                throw rethrowCheckedExceptionFromServiceSpecificException(e);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-
-        /**
-         * Update the underlying network for this IpSecTunnelInterface.
-         *
-         * <p>This new underlying network will be used for all transforms applied AFTER this call is
-         * complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to
-         * this tunnel interface, traffic will still use the old SA, and be routed on the old
-         * underlying network.
-         *
-         * <p>To migrate IPsec tunnel mode traffic, a caller should:
-         *
-         * <ol>
-         *   <li>Update the IpSecTunnelInterface’s underlying network.
-         *   <li>Apply {@link IpSecTransform}(s) with matching addresses to this
-         *       IpSecTunnelInterface.
-         * </ol>
-         *
-         * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
-         *     This network MUST never be the network exposing this IpSecTunnelInterface, otherwise
-         *     this method will throw an {@link IllegalArgumentException}. If the
-         *     IpSecTunnelInterface is later added to this network, all outbound traffic will be
-         *     blackholed.
-         */
-        // TODO: b/169171001 Update the documentation when transform migration is supported.
-        // The purpose of making updating network and applying transforms separate is to leave open
-        // the possibility to support lossless migration procedures. To do that, Android platform
-        // will need to support multiple inbound tunnel mode transforms, just like it can support
-        // multiple transport mode transforms.
-        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-        public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException {
-            try {
-                mService.setNetworkForTunnelInterface(
-                        mResourceId, underlyingNetwork, mOpPackageName);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-
-        private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service,
-                @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
-                @NonNull Network underlyingNetwork)
-                throws ResourceUnavailableException, IOException {
-            mOpPackageName = ctx.getOpPackageName();
-            mService = service;
-            mLocalAddress = localAddress;
-            mRemoteAddress = remoteAddress;
-            mUnderlyingNetwork = underlyingNetwork;
-
-            try {
-                IpSecTunnelInterfaceResponse result =
-                        mService.createTunnelInterface(
-                                localAddress.getHostAddress(),
-                                remoteAddress.getHostAddress(),
-                                underlyingNetwork,
-                                new Binder(),
-                                mOpPackageName);
-                switch (result.status) {
-                    case Status.OK:
-                        break;
-                    case Status.RESOURCE_UNAVAILABLE:
-                        throw new ResourceUnavailableException(
-                                "No more tunnel interfaces may be allocated by this requester.");
-                    default:
-                        throw new RuntimeException(
-                                "Unknown status returned by IpSecService: " + result.status);
-                }
-                mResourceId = result.resourceId;
-                mInterfaceName = result.interfaceName;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            mCloseGuard.open("constructor");
-        }
-
-        /**
-         * Delete an IpSecTunnelInterface
-         *
-         * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
-         * resources. Any packets bound for this interface either inbound or outbound will
-         * all be lost.
-         */
-        @Override
-        public void close() {
-            try {
-                mService.deleteTunnelInterface(mResourceId, mOpPackageName);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            } catch (Exception e) {
-                // On close we swallow all random exceptions since failure to close is not
-                // actionable by the user.
-                Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
-            } finally {
-                mResourceId = INVALID_RESOURCE_ID;
-                mCloseGuard.close();
-            }
-        }
-
-        /** Check that the Interface was closed properly. */
-        @Override
-        protected void finalize() throws Throwable {
-            if (mCloseGuard != null) {
-                mCloseGuard.warnIfOpen();
-            }
-            close();
-        }
-
-        /** @hide */
-        @VisibleForTesting
-        public int getResourceId() {
-            return mResourceId;
-        }
-
-        @NonNull
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                .append("IpSecTunnelInterface{ifname=")
-                .append(mInterfaceName)
-                .append(",resourceId=")
-                .append(mResourceId)
-                .append("}")
-                .toString();
-        }
-    }
-
-    /**
-     * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
-     *
-     * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the
-     * underlying network goes away, and the onLost() callback is received.
-     *
-     * @param localAddress The local addres of the tunnel
-     * @param remoteAddress The local addres of the tunnel
-     * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
-     *        This network should almost certainly be a network such as WiFi with an L2 address.
-     * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
-     * @throws IOException indicating that the socket could not be opened or bound
-     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
-     * @hide
-     */
-    @SystemApi
-    @NonNull
-    @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-    @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-    public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
-            @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
-            throws ResourceUnavailableException, IOException {
-        try {
-            return new IpSecTunnelInterface(
-                    mContext, mService, localAddress, remoteAddress, underlyingNetwork);
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        }
-    }
-
-    /**
-     * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will
-     * tunnel all traffic for the given direction through the underlying network's interface with
-     * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional
-     * IP header and IPsec Header on all inbound traffic).
-     * <p>Applications should probably not use this API directly.
-     *
-     *
-     * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
-     *        transform.
-     * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
-     *        the transform will be used.
-     * @param transform an {@link IpSecTransform} created in tunnel mode
-     * @throws IOException indicating that the transform could not be applied due to a lower
-     *         layer failure.
-     * @hide
-     */
-    @SystemApi
-    @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-    @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-    public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel,
-            @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException {
-        try {
-            mService.applyTunnelModeTransform(
-                    tunnel.getResourceId(), direction,
-                    transform.getResourceId(), mContext.getOpPackageName());
-        } catch (ServiceSpecificException e) {
-            throw rethrowCheckedExceptionFromServiceSpecificException(e);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder,
-            String callingPackage) {
-        try {
-            return mService.createTransform(config, binder, callingPackage);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void deleteTransform(int resourceId) {
-        try {
-            mService.deleteTransform(resourceId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Construct an instance of IpSecManager within an application context.
-     *
-     * @param context the application context for this manager
-     * @hide
-     */
-    public IpSecManager(Context ctx, IIpSecService service) {
-        mContext = ctx;
-        mService = Objects.requireNonNull(service, "missing service");
-    }
-
-    private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) {
-        // OsConstants are late binding, so switch statements can't be used.
-        if (sse.errorCode == OsConstants.EINVAL) {
-            throw new IllegalArgumentException(sse);
-        } else if (sse.errorCode == OsConstants.EAGAIN) {
-            throw new IllegalStateException(sse);
-        } else if (sse.errorCode == OsConstants.EOPNOTSUPP
-                || sse.errorCode == OsConstants.EPROTONOSUPPORT) {
-            throw new UnsupportedOperationException(sse);
-        }
-    }
-
-    /**
-     * Convert an Errno SSE to the correct Unchecked exception type.
-     *
-     * This method never actually returns.
-     */
-    // package
-    static RuntimeException
-            rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) {
-        maybeHandleServiceSpecificException(sse);
-        throw new RuntimeException(sse);
-    }
-
-    /**
-     * Convert an Errno SSE to the correct Checked or Unchecked exception type.
-     *
-     * This method may throw IOException, or it may throw an unchecked exception; it will never
-     * actually return.
-     */
-    // package
-    static IOException rethrowCheckedExceptionFromServiceSpecificException(
-            ServiceSpecificException sse) throws IOException {
-        // First see if this is an unchecked exception of a type we know.
-        // If so, then we prefer the unchecked (specific) type of exception.
-        maybeHandleServiceSpecificException(sse);
-        // If not, then all we can do is provide the SSE in the form of an IOException.
-        throw new ErrnoException(
-                "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException();
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl
deleted file mode 100644
index 6484a00..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-parcelable IpSecSpiResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java
deleted file mode 100644
index f99e570..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an SPI and corresponding status from the IpSecService to an
- * IpSecManager.SecurityParameterIndex.
- *
- * @hide
- */
-public final class IpSecSpiResponse implements Parcelable {
-    private static final String TAG = "IpSecSpiResponse";
-
-    public final int resourceId;
-    public final int status;
-    public final int spi;
-    // Parcelable Methods
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(status);
-        out.writeInt(resourceId);
-        out.writeInt(spi);
-    }
-
-    public IpSecSpiResponse(int inStatus, int inResourceId, int inSpi) {
-        status = inStatus;
-        resourceId = inResourceId;
-        spi = inSpi;
-    }
-
-    public IpSecSpiResponse(int inStatus) {
-        if (inStatus == IpSecManager.Status.OK) {
-            throw new IllegalArgumentException("Valid status implies other args must be provided");
-        }
-        status = inStatus;
-        resourceId = IpSecManager.INVALID_RESOURCE_ID;
-        spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-    }
-
-    private IpSecSpiResponse(Parcel in) {
-        status = in.readInt();
-        resourceId = in.readInt();
-        spi = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<IpSecSpiResponse> CREATOR =
-            new Parcelable.Creator<IpSecSpiResponse>() {
-                public IpSecSpiResponse createFromParcel(Parcel in) {
-                    return new IpSecSpiResponse(in);
-                }
-
-                public IpSecSpiResponse[] newArray(int size) {
-                    return new IpSecSpiResponse[size];
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
deleted file mode 100644
index 68ae5de..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import static android.net.IpSecManager.INVALID_RESOURCE_ID;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.ServiceSpecificException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import dalvik.system.CloseGuard;
-
-import java.io.IOException;
-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.
- *
- * <p>Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform}
- * object encapsulates the properties and state of an IPsec security association. That includes,
- * but is not limited to, algorithm choice, key material, and allocated system resources.
- *
- * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
- *     Internet Protocol</a>
- */
-public final class IpSecTransform implements AutoCloseable {
-    private static final String TAG = "IpSecTransform";
-
-    /** @hide */
-    public static final int MODE_TRANSPORT = 0;
-
-    /** @hide */
-    public static final int MODE_TUNNEL = 1;
-
-    /** @hide */
-    public static final int ENCAP_NONE = 0;
-
-    /**
-     * IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP
-     * header and payload. This prevents traffic from being interpreted as ESP or IKEv2.
-     *
-     * @hide
-     */
-    public static final int ENCAP_ESPINUDP_NON_IKE = 1;
-
-    /**
-     * IPsec traffic will be encapsulated within UDP as per
-     * <a href="https://tools.ietf.org/html/rfc3948">RFC 3498</a>.
-     *
-     * @hide
-     */
-    public static final int ENCAP_ESPINUDP = 2;
-
-    /** @hide */
-    @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface EncapType {}
-
-    /** @hide */
-    @VisibleForTesting
-    public IpSecTransform(Context context, IpSecConfig config) {
-        mContext = context;
-        mConfig = new IpSecConfig(config);
-        mResourceId = INVALID_RESOURCE_ID;
-    }
-
-    private IpSecManager getIpSecManager(Context context) {
-        return context.getSystemService(IpSecManager.class);
-    }
-    /**
-     * Checks the result status and throws an appropriate exception if the status is not Status.OK.
-     */
-    private void checkResultStatus(int status)
-            throws IOException, IpSecManager.ResourceUnavailableException,
-                    IpSecManager.SpiUnavailableException {
-        switch (status) {
-            case IpSecManager.Status.OK:
-                return;
-                // TODO: Pass Error string back from bundle so that errors can be more specific
-            case IpSecManager.Status.RESOURCE_UNAVAILABLE:
-                throw new IpSecManager.ResourceUnavailableException(
-                        "Failed to allocate a new IpSecTransform");
-            case IpSecManager.Status.SPI_UNAVAILABLE:
-                Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
-                // Fall through
-            default:
-                throw new IllegalStateException(
-                        "Failed to Create a Transform with status code " + status);
-        }
-    }
-
-    private IpSecTransform activate()
-            throws IOException, IpSecManager.ResourceUnavailableException,
-                    IpSecManager.SpiUnavailableException {
-        synchronized (this) {
-            try {
-                IpSecTransformResponse result = getIpSecManager(mContext).createTransform(
-                        mConfig, new Binder(), mContext.getOpPackageName());
-                int status = result.status;
-                checkResultStatus(status);
-                mResourceId = result.resourceId;
-                Log.d(TAG, "Added Transform with Id " + mResourceId);
-                mCloseGuard.open("build");
-            } catch (ServiceSpecificException e) {
-                throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
-            }
-        }
-
-        return this;
-    }
-
-    /**
-     * Standard equals.
-     */
-    public boolean equals(@Nullable Object other) {
-        if (this == other) return true;
-        if (!(other instanceof IpSecTransform)) return false;
-        final IpSecTransform rhs = (IpSecTransform) other;
-        return getConfig().equals(rhs.getConfig()) && mResourceId == rhs.mResourceId;
-    }
-
-    /**
-     * Deactivate this {@code IpSecTransform} and free allocated resources.
-     *
-     * <p>Deactivating a transform while it is still applied to a socket will result in errors on
-     * that socket. Make sure to remove transforms by calling {@link
-     * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a
-     * socket will not deactivate it (because one transform may be applied to multiple sockets).
-     *
-     * <p>It is safe to call this method on a transform that has already been deactivated.
-     */
-    public void close() {
-        Log.d(TAG, "Removing Transform with Id " + mResourceId);
-
-        // Always safe to attempt cleanup
-        if (mResourceId == INVALID_RESOURCE_ID) {
-            mCloseGuard.close();
-            return;
-        }
-        try {
-            getIpSecManager(mContext).deleteTransform(mResourceId);
-        } catch (Exception e) {
-            // On close we swallow all random exceptions since failure to close is not
-            // actionable by the user.
-            Log.e(TAG, "Failed to close " + this + ", Exception=" + e);
-        } finally {
-            mResourceId = INVALID_RESOURCE_ID;
-            mCloseGuard.close();
-        }
-    }
-
-    /** Check that the transform was closed properly. */
-    @Override
-    protected void finalize() throws Throwable {
-        if (mCloseGuard != null) {
-            mCloseGuard.warnIfOpen();
-        }
-        close();
-    }
-
-    /* Package */
-    IpSecConfig getConfig() {
-        return mConfig;
-    }
-
-    private final IpSecConfig mConfig;
-    private int mResourceId;
-    private final Context mContext;
-    private final CloseGuard mCloseGuard = CloseGuard.get();
-
-    /** @hide */
-    @VisibleForTesting
-    public int getResourceId() {
-        return mResourceId;
-    }
-
-    /**
-     * A callback class to provide status information regarding a NAT-T keepalive session
-     *
-     * <p>Use this callback to receive status information regarding a NAT-T keepalive session
-     * by registering it when calling {@link #startNattKeepalive}.
-     *
-     * @hide
-     */
-    public static class NattKeepaliveCallback {
-        /** The specified {@code Network} is not connected. */
-        public static final int ERROR_INVALID_NETWORK = 1;
-        /** The hardware does not support this request. */
-        public static final int ERROR_HARDWARE_UNSUPPORTED = 2;
-        /** The hardware returned an error. */
-        public static final int ERROR_HARDWARE_ERROR = 3;
-
-        /** The requested keepalive was successfully started. */
-        public void onStarted() {}
-        /** The keepalive was successfully stopped. */
-        public void onStopped() {}
-        /** An error occurred. */
-        public void onError(int error) {}
-    }
-
-    /** This class is used to build {@link IpSecTransform} objects. */
-    public static class Builder {
-        private Context mContext;
-        private IpSecConfig mConfig;
-
-        /**
-         * Set the encryption algorithm.
-         *
-         * <p>Encryption is mutually exclusive with authenticated encryption.
-         *
-         * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
-         */
-        @NonNull
-        public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) {
-            // TODO: throw IllegalArgumentException if algo is not an encryption algorithm.
-            Objects.requireNonNull(algo);
-            mConfig.setEncryption(algo);
-            return this;
-        }
-
-        /**
-         * Set the authentication (integrity) algorithm.
-         *
-         * <p>Authentication is mutually exclusive with authenticated encryption.
-         *
-         * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
-         */
-        @NonNull
-        public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) {
-            // TODO: throw IllegalArgumentException if algo is not an authentication algorithm.
-            Objects.requireNonNull(algo);
-            mConfig.setAuthentication(algo);
-            return this;
-        }
-
-        /**
-         * Set the authenticated encryption algorithm.
-         *
-         * <p>The Authenticated Encryption (AE) class of algorithms are also known as
-         * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode
-         * algorithms (as referred to in
-         * <a href="https://tools.ietf.org/html/rfc4301">RFC 4301</a>).
-         *
-         * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
-         *
-         * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
-         *     be applied.
-         */
-        @NonNull
-        public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) {
-            Objects.requireNonNull(algo);
-            mConfig.setAuthenticatedEncryption(algo);
-            return this;
-        }
-
-        /**
-         * Add UDP encapsulation to an IPv4 transform.
-         *
-         * <p>This allows IPsec traffic to pass through a NAT.
-         *
-         * @see <a href="https://tools.ietf.org/html/rfc3948">RFC 3948, UDP Encapsulation of IPsec
-         *     ESP Packets</a>
-         * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.23">RFC 7296 section 2.23,
-         *     NAT Traversal of IKEv2</a>
-         * @param localSocket a socket for sending and receiving encapsulated traffic
-         * @param remotePort the UDP port number of the remote host that will send and receive
-         *     encapsulated traffic. In the case of IKEv2, this should be port 4500.
-         */
-        @NonNull
-        public IpSecTransform.Builder setIpv4Encapsulation(
-                @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
-            Objects.requireNonNull(localSocket);
-            mConfig.setEncapType(ENCAP_ESPINUDP);
-            if (localSocket.getResourceId() == INVALID_RESOURCE_ID) {
-                throw new IllegalArgumentException("Invalid UdpEncapsulationSocket");
-            }
-            mConfig.setEncapSocketResourceId(localSocket.getResourceId());
-            mConfig.setEncapRemotePort(remotePort);
-            return this;
-        }
-
-        /**
-         * Build a transport mode {@link IpSecTransform}.
-         *
-         * <p>This builds and activates a transport mode transform. Note that an active transform
-         * will not affect any network traffic until it has been applied to one or more sockets.
-         *
-         * @see IpSecManager#applyTransportModeTransform
-         * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use
-         *     this transform; this address must belong to the Network used by all sockets that
-         *     utilize this transform; if provided, then only traffic originating from the
-         *     specified source address will be processed.
-         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
-         *     traffic
-         * @throws IllegalArgumentException indicating that a particular combination of transform
-         *     properties is invalid
-         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
-         *     are active
-         * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
-         *     collides with an existing transform
-         * @throws IOException indicating other errors
-         */
-        @NonNull
-        public IpSecTransform buildTransportModeTransform(
-                @NonNull InetAddress sourceAddress,
-                @NonNull IpSecManager.SecurityParameterIndex spi)
-                throws IpSecManager.ResourceUnavailableException,
-                        IpSecManager.SpiUnavailableException, IOException {
-            Objects.requireNonNull(sourceAddress);
-            Objects.requireNonNull(spi);
-            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
-                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
-            }
-            mConfig.setMode(MODE_TRANSPORT);
-            mConfig.setSourceAddress(sourceAddress.getHostAddress());
-            mConfig.setSpiResourceId(spi.getResourceId());
-            // FIXME: modifying a builder after calling build can change the built transform.
-            return new IpSecTransform(mContext, mConfig).activate();
-        }
-
-        /**
-         * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
-         * parameters have interdependencies that are checked at build time.
-         *
-         * @param sourceAddress the {@link InetAddress} that provides the source address for this
-         *     IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
-         *     that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
-         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
-         *     traffic
-         * @throws IllegalArgumentException indicating that a particular combination of transform
-         *     properties is invalid.
-         * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms
-         *     are active
-         * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI
-         *     collides with an existing transform
-         * @throws IOException indicating other errors
-         * @hide
-         */
-        @SystemApi
-        @NonNull
-        @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
-        @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS)
-        public IpSecTransform buildTunnelModeTransform(
-                @NonNull InetAddress sourceAddress,
-                @NonNull IpSecManager.SecurityParameterIndex spi)
-                throws IpSecManager.ResourceUnavailableException,
-                        IpSecManager.SpiUnavailableException, IOException {
-            Objects.requireNonNull(sourceAddress);
-            Objects.requireNonNull(spi);
-            if (spi.getResourceId() == INVALID_RESOURCE_ID) {
-                throw new IllegalArgumentException("Invalid SecurityParameterIndex");
-            }
-            mConfig.setMode(MODE_TUNNEL);
-            mConfig.setSourceAddress(sourceAddress.getHostAddress());
-            mConfig.setSpiResourceId(spi.getResourceId());
-            return new IpSecTransform(mContext, mConfig).activate();
-        }
-
-        /**
-         * Create a new IpSecTransform.Builder.
-         *
-         * @param context current context
-         */
-        public Builder(@NonNull Context context) {
-            Objects.requireNonNull(context);
-            mContext = context;
-            mConfig = new IpSecConfig();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return new StringBuilder()
-            .append("IpSecTransform{resourceId=")
-            .append(mResourceId)
-            .append("}")
-            .toString();
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl
deleted file mode 100644
index 546230d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-parcelable IpSecTransformResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java
deleted file mode 100644
index 363f316..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an IpSecTransform resource Id and and corresponding status from the
- * IpSecService to an IpSecTransform object.
- *
- * @hide
- */
-public final class IpSecTransformResponse implements Parcelable {
-    private static final String TAG = "IpSecTransformResponse";
-
-    public final int resourceId;
-    public final int status;
-    // Parcelable Methods
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(status);
-        out.writeInt(resourceId);
-    }
-
-    public IpSecTransformResponse(int inStatus) {
-        if (inStatus == IpSecManager.Status.OK) {
-            throw new IllegalArgumentException("Valid status implies other args must be provided");
-        }
-        status = inStatus;
-        resourceId = IpSecManager.INVALID_RESOURCE_ID;
-    }
-
-    public IpSecTransformResponse(int inStatus, int inResourceId) {
-        status = inStatus;
-        resourceId = inResourceId;
-    }
-
-    private IpSecTransformResponse(Parcel in) {
-        status = in.readInt();
-        resourceId = in.readInt();
-    }
-
-    @android.annotation.NonNull
-    public static final Parcelable.Creator<IpSecTransformResponse> CREATOR =
-            new Parcelable.Creator<IpSecTransformResponse>() {
-                public IpSecTransformResponse createFromParcel(Parcel in) {
-                    return new IpSecTransformResponse(in);
-                }
-
-                public IpSecTransformResponse[] newArray(int size) {
-                    return new IpSecTransformResponse[size];
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
deleted file mode 100644
index 7239221..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-parcelable IpSecTunnelInterfaceResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
deleted file mode 100644
index 127e30a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This class is used to return an IpSecTunnelInterface resource Id and and corresponding status
- * from the IpSecService to an IpSecTunnelInterface object.
- *
- * @hide
- */
-public final class IpSecTunnelInterfaceResponse implements Parcelable {
-    private static final String TAG = "IpSecTunnelInterfaceResponse";
-
-    public final int resourceId;
-    public final String interfaceName;
-    public final int status;
-    // Parcelable Methods
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(status);
-        out.writeInt(resourceId);
-        out.writeString(interfaceName);
-    }
-
-    public IpSecTunnelInterfaceResponse(int inStatus) {
-        if (inStatus == IpSecManager.Status.OK) {
-            throw new IllegalArgumentException("Valid status implies other args must be provided");
-        }
-        status = inStatus;
-        resourceId = IpSecManager.INVALID_RESOURCE_ID;
-        interfaceName = "";
-    }
-
-    public IpSecTunnelInterfaceResponse(int inStatus, int inResourceId, String inInterfaceName) {
-        status = inStatus;
-        resourceId = inResourceId;
-        interfaceName = inInterfaceName;
-    }
-
-    private IpSecTunnelInterfaceResponse(Parcel in) {
-        status = in.readInt();
-        resourceId = in.readInt();
-        interfaceName = in.readString();
-    }
-
-    @android.annotation.NonNull
-    public static final Parcelable.Creator<IpSecTunnelInterfaceResponse> CREATOR =
-            new Parcelable.Creator<IpSecTunnelInterfaceResponse>() {
-                public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) {
-                    return new IpSecTunnelInterfaceResponse(in);
-                }
-
-                public IpSecTunnelInterfaceResponse[] newArray(int size) {
-                    return new IpSecTunnelInterfaceResponse[size];
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
deleted file mode 100644
index 5e451f3..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-/** @hide */
-parcelable IpSecUdpEncapResponse;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
deleted file mode 100644
index 732cf19..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.net;
-
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * This class is used to return a UDP Socket and corresponding status from the IpSecService to an
- * IpSecManager.UdpEncapsulationSocket.
- *
- * @hide
- */
-public final class IpSecUdpEncapResponse implements Parcelable {
-    private static final String TAG = "IpSecUdpEncapResponse";
-
-    public final int resourceId;
-    public final int port;
-    public final int status;
-    // There is a weird asymmetry with FileDescriptor: you can write a FileDescriptor
-    // but you read a ParcelFileDescriptor. To circumvent this, when we receive a FD
-    // from the user, we immediately create a ParcelFileDescriptor DUP, which we invalidate
-    // on writeParcel() by setting the flag to do close-on-write.
-    // TODO: tests to ensure this doesn't leak
-    public final ParcelFileDescriptor fileDescriptor;
-
-    // Parcelable Methods
-
-    @Override
-    public int describeContents() {
-        return (fileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(status);
-        out.writeInt(resourceId);
-        out.writeInt(port);
-        out.writeParcelable(fileDescriptor, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-    }
-
-    public IpSecUdpEncapResponse(int inStatus) {
-        if (inStatus == IpSecManager.Status.OK) {
-            throw new IllegalArgumentException("Valid status implies other args must be provided");
-        }
-        status = inStatus;
-        resourceId = IpSecManager.INVALID_RESOURCE_ID;
-        port = -1;
-        fileDescriptor = null; // yes I know it's redundant, but readability
-    }
-
-    public IpSecUdpEncapResponse(int inStatus, int inResourceId, int inPort, FileDescriptor inFd)
-            throws IOException {
-        if (inStatus == IpSecManager.Status.OK && inFd == null) {
-            throw new IllegalArgumentException("Valid status implies FD must be non-null");
-        }
-        status = inStatus;
-        resourceId = inResourceId;
-        port = inPort;
-        fileDescriptor = (status == IpSecManager.Status.OK) ? ParcelFileDescriptor.dup(inFd) : null;
-    }
-
-    private IpSecUdpEncapResponse(Parcel in) {
-        status = in.readInt();
-        resourceId = in.readInt();
-        port = in.readInt();
-        fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
-    }
-
-    @android.annotation.NonNull
-    public static final Parcelable.Creator<IpSecUdpEncapResponse> CREATOR =
-            new Parcelable.Creator<IpSecUdpEncapResponse>() {
-                public IpSecUdpEncapResponse createFromParcel(Parcel in) {
-                    return new IpSecUdpEncapResponse(in);
-                }
-
-                public IpSecUdpEncapResponse[] newArray(int size) {
-                    return new IpSecUdpEncapResponse[size];
-                }
-            };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
deleted file mode 100644
index da5f88d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.net.wifi.WifiInfo;
-import android.service.NetworkIdentityProto;
-import android.telephony.TelephonyManager;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkCapabilitiesUtils;
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Objects;
-
-/**
- * Network definition that includes strong identity. Analogous to combining
- * {@link NetworkCapabilities} and an IMSI.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public class NetworkIdentity {
-    private static final String TAG = "NetworkIdentity";
-
-    /** @hide */
-    // TODO: Remove this after migrating all callers to use
-    //  {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
-    public static final int SUBTYPE_COMBINED = -1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
-            NetworkTemplate.OEM_MANAGED_NO,
-            NetworkTemplate.OEM_MANAGED_PAID,
-            NetworkTemplate.OEM_MANAGED_PRIVATE
-    })
-    public @interface OemManaged{}
-
-    /**
-     * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
-     * @hide
-     */
-    public static final int OEM_NONE = 0x0;
-    /**
-     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
-     * @hide
-     */
-    public static final int OEM_PAID = 1 << 0;
-    /**
-     * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
-     * @hide
-     */
-    public static final int OEM_PRIVATE = 1 << 1;
-
-    private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
-
-    final int mType;
-    final int mRatType;
-    final int mSubId;
-    final String mSubscriberId;
-    final String mWifiNetworkKey;
-    final boolean mRoaming;
-    final boolean mMetered;
-    final boolean mDefaultNetwork;
-    final int mOemManaged;
-
-    /** @hide */
-    public NetworkIdentity(
-            int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
-            boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) {
-        mType = type;
-        mRatType = ratType;
-        mSubscriberId = subscriberId;
-        mWifiNetworkKey = wifiNetworkKey;
-        mRoaming = roaming;
-        mMetered = metered;
-        mDefaultNetwork = defaultNetwork;
-        mOemManaged = oemManaged;
-        mSubId = subId;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
-                mDefaultNetwork, mOemManaged, mSubId);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (obj instanceof NetworkIdentity) {
-            final NetworkIdentity ident = (NetworkIdentity) obj;
-            return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
-                    && Objects.equals(mSubscriberId, ident.mSubscriberId)
-                    && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
-                    && mMetered == ident.mMetered
-                    && mDefaultNetwork == ident.mDefaultNetwork
-                    && mOemManaged == ident.mOemManaged
-                    && mSubId == ident.mSubId;
-        }
-        return false;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder builder = new StringBuilder("{");
-        builder.append("type=").append(mType);
-        builder.append(", ratType=");
-        if (mRatType == NETWORK_TYPE_ALL) {
-            builder.append("COMBINED");
-        } else {
-            builder.append(mRatType);
-        }
-        if (mSubscriberId != null) {
-            builder.append(", subscriberId=")
-                    .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
-        }
-        if (mWifiNetworkKey != null) {
-            builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
-        }
-        if (mRoaming) {
-            builder.append(", ROAMING");
-        }
-        builder.append(", metered=").append(mMetered);
-        builder.append(", defaultNetwork=").append(mDefaultNetwork);
-        builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
-        builder.append(", subId=").append(mSubId);
-        return builder.append("}").toString();
-    }
-
-    /**
-     * Get the human readable representation of a bitfield representing the OEM managed state of a
-     * network.
-     */
-    static String getOemManagedNames(int oemManaged) {
-        if (oemManaged == OEM_NONE) {
-            return "OEM_NONE";
-        }
-        final int[] bitPositions = NetworkCapabilitiesUtils.unpackBits(oemManaged);
-        final ArrayList<String> oemManagedNames = new ArrayList<String>();
-        for (int position : bitPositions) {
-            oemManagedNames.add(nameOfOemManaged(1 << position));
-        }
-        return String.join(",", oemManagedNames);
-    }
-
-    private static String nameOfOemManaged(int oemManagedBit) {
-        switch (oemManagedBit) {
-            case OEM_PAID:
-                return "OEM_PAID";
-            case OEM_PRIVATE:
-                return "OEM_PRIVATE";
-            default:
-                return "Invalid(" + oemManagedBit + ")";
-        }
-    }
-
-    /** @hide */
-    public void dumpDebug(ProtoOutputStream proto, long tag) {
-        final long start = proto.start(tag);
-
-        proto.write(NetworkIdentityProto.TYPE, mType);
-
-        // TODO: dump mRatType as well.
-
-        proto.write(NetworkIdentityProto.ROAMING, mRoaming);
-        proto.write(NetworkIdentityProto.METERED, mMetered);
-        proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
-        proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged);
-
-        proto.end(start);
-    }
-
-    /** Get the network type of this instance. */
-    public int getType() {
-        return mType;
-    }
-
-    /** Get the Radio Access Technology(RAT) type of this instance. */
-    public int getRatType() {
-        return mRatType;
-    }
-
-    /** Get the Subscriber Id of this instance. */
-    @Nullable
-    public String getSubscriberId() {
-        return mSubscriberId;
-    }
-
-    /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
-    @Nullable
-    public String getWifiNetworkKey() {
-        return mWifiNetworkKey;
-    }
-
-    /** @hide */
-    // TODO: Remove this function after all callers are removed.
-    public boolean getRoaming() {
-        return mRoaming;
-    }
-
-    /** Return whether this network is roaming. */
-    public boolean isRoaming() {
-        return mRoaming;
-    }
-
-    /** @hide */
-    // TODO: Remove this function after all callers are removed.
-    public boolean getMetered() {
-        return mMetered;
-    }
-
-    /** Return whether this network is metered. */
-    public boolean isMetered() {
-        return mMetered;
-    }
-
-    /** @hide */
-    // TODO: Remove this function after all callers are removed.
-    public boolean getDefaultNetwork() {
-        return mDefaultNetwork;
-    }
-
-    /** Return whether this network is the default network. */
-    public boolean isDefaultNetwork() {
-        return mDefaultNetwork;
-    }
-
-    /** Get the OEM managed type of this instance. */
-    public int getOemManaged() {
-        return mOemManaged;
-    }
-
-    /** Get the SubId of this instance. */
-    public int getSubId() {
-        return mSubId;
-    }
-
-    /**
-     * Assemble a {@link NetworkIdentity} from the passed arguments.
-     *
-     * This methods builds an identity based on the capabilities of the network in the
-     * snapshot and other passed arguments. The identity is used as a key to record data usage.
-     *
-     * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
-     * @param defaultNetwork whether the network is a default network.
-     * @param ratType the Radio Access Technology(RAT) type of the network. Or
-     *                {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
-     *                See {@code TelephonyManager.NETWORK_TYPE_*}.
-     * @hide
-     * @deprecated See {@link NetworkIdentity.Builder}.
-     */
-    // TODO: Remove this after all callers are migrated to use new Api.
-    @Deprecated
-    @NonNull
-    public static NetworkIdentity buildNetworkIdentity(Context context,
-            @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
-        final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
-                .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork)
-                .setSubId(snapshot.getSubId());
-        if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
-            builder.setRatType(ratType);
-        }
-        return builder.build();
-    }
-
-    /**
-     * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
-     * @hide
-     */
-    public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
-        int oemManaged = OEM_NONE;
-
-        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
-            oemManaged |= OEM_PAID;
-        }
-        if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) {
-            oemManaged |= OEM_PRIVATE;
-        }
-
-        return oemManaged;
-    }
-
-    /** @hide */
-    public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
-        Objects.requireNonNull(right);
-        int res = Integer.compare(left.mType, right.mType);
-        if (res == 0) {
-            res = Integer.compare(left.mRatType, right.mRatType);
-        }
-        if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
-            res = left.mSubscriberId.compareTo(right.mSubscriberId);
-        }
-        if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
-            res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
-        }
-        if (res == 0) {
-            res = Boolean.compare(left.mRoaming, right.mRoaming);
-        }
-        if (res == 0) {
-            res = Boolean.compare(left.mMetered, right.mMetered);
-        }
-        if (res == 0) {
-            res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
-        }
-        if (res == 0) {
-            res = Integer.compare(left.mOemManaged, right.mOemManaged);
-        }
-        if (res == 0) {
-            res = Integer.compare(left.mSubId, right.mSubId);
-        }
-        return res;
-    }
-
-    /**
-     * Builder class for {@link NetworkIdentity}.
-     */
-    public static final class Builder {
-        // Need to be synchronized with ConnectivityManager.
-        // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
-        private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
-        private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
-
-        private int mType;
-        private int mRatType;
-        private String mSubscriberId;
-        private String mWifiNetworkKey;
-        private boolean mRoaming;
-        private boolean mMetered;
-        private boolean mDefaultNetwork;
-        private int mOemManaged;
-        private int mSubId;
-
-        /**
-         * Creates a new Builder.
-         */
-        public Builder() {
-            // Initialize with default values. Will be overwritten by setters.
-            mType = ConnectivityManager.TYPE_NONE;
-            mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
-            mSubscriberId = null;
-            mWifiNetworkKey = null;
-            mRoaming = false;
-            mMetered = false;
-            mDefaultNetwork = false;
-            mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
-            mSubId = INVALID_SUBSCRIPTION_ID;
-        }
-
-        /**
-         * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
-         * This is a useful shorthand that will read from the snapshot and set the
-         * following fields, if they are set in the snapshot :
-         *  - type
-         *  - subscriberId
-         *  - roaming
-         *  - metered
-         *  - oemManaged
-         *  - wifiNetworkKey
-         *
-         * @param snapshot The target {@link NetworkStateSnapshot} object.
-         * @return The builder object.
-         */
-        @SuppressLint("MissingGetterMatchingBuilder")
-        @NonNull
-        public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
-            setType(snapshot.getLegacyType());
-
-            setSubscriberId(snapshot.getSubscriberId());
-            setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
-                    NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
-            setMetered(!(snapshot.getNetworkCapabilities().hasCapability(
-                    NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
-                    || snapshot.getNetworkCapabilities().hasCapability(
-                    NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)));
-
-            setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
-
-            if (mType == TYPE_WIFI) {
-                final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
-                        .getTransportInfo();
-                if (transportInfo instanceof WifiInfo) {
-                    final WifiInfo info = (WifiInfo) transportInfo;
-                    setWifiNetworkKey(info.getNetworkKey());
-                }
-            }
-            return this;
-        }
-
-        /**
-         * Set the network type of the network.
-         *
-         * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
-         *
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setType(int type) {
-            // Include TYPE_NONE for compatibility, type field might not be filled by some
-            // networks such as test networks.
-            if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
-                    && type != ConnectivityManager.TYPE_NONE) {
-                throw new IllegalArgumentException("Invalid network type: " + type);
-            }
-            mType = type;
-            return this;
-        }
-
-        /**
-         * Set the Radio Access Technology(RAT) type of the network.
-         *
-         * No RAT type is specified by default. Call clearRatType to reset.
-         *
-         * @param ratType the Radio Access Technology(RAT) type if applicable. See
-         *                {@code TelephonyManager.NETWORK_TYPE_*}.
-         *
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setRatType(int ratType) {
-            if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
-                    && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
-                    && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) {
-                throw new IllegalArgumentException("Invalid ratType " + ratType);
-            }
-            mRatType = ratType;
-            return this;
-        }
-
-        /**
-         * Clear the Radio Access Technology(RAT) type of the network.
-         *
-         * @return this builder.
-         */
-        @NonNull
-        public Builder clearRatType() {
-            mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
-            return this;
-        }
-
-        /**
-         * Set the Subscriber Id.
-         *
-         * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setSubscriberId(@Nullable String subscriberId) {
-            mSubscriberId = subscriberId;
-            return this;
-        }
-
-        /**
-         * Set the Wifi Network Key.
-         *
-         * @param wifiNetworkKey Wifi Network Key of the network,
-         *                        see {@link WifiInfo#getNetworkKey()}.
-         *                        Or null if not applicable.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
-            mWifiNetworkKey = wifiNetworkKey;
-            return this;
-        }
-
-        /**
-         * Set whether this network is roaming.
-         *
-         * This field is false by default. Call with false to reset.
-         *
-         * @param roaming the roaming status of the network.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setRoaming(boolean roaming) {
-            mRoaming = roaming;
-            return this;
-        }
-
-        /**
-         * Set whether this network is metered.
-         *
-         * This field is false by default. Call with false to reset.
-         *
-         * @param metered the meteredness of the network.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setMetered(boolean metered) {
-            mMetered = metered;
-            return this;
-        }
-
-        /**
-         * Set whether this network is the default network.
-         *
-         * This field is false by default. Call with false to reset.
-         *
-         * @param defaultNetwork the default network status of the network.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setDefaultNetwork(boolean defaultNetwork) {
-            mDefaultNetwork = defaultNetwork;
-            return this;
-        }
-
-        /**
-         * Set the OEM managed type.
-         *
-         * @param oemManaged Type of OEM managed network or unmanaged networks.
-         *                   See {@code NetworkTemplate#OEM_MANAGED_*}.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setOemManaged(@OemManaged int oemManaged) {
-            // Assert input does not contain illegal oemManage bits.
-            if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
-                throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
-            }
-            mOemManaged = oemManaged;
-            return this;
-        }
-
-        /**
-         * Set the Subscription Id.
-         *
-         * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not
-         *              applicable.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setSubId(int subId) {
-            mSubId = subId;
-            return this;
-        }
-
-        private void ensureValidParameters() {
-            // Assert non-mobile network cannot have a ratType.
-            if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
-                throw new IllegalArgumentException(
-                        "Invalid ratType " + mRatType + " for type " + mType);
-            }
-
-            // Assert non-wifi network cannot have a wifi network key.
-            if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
-                throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
-            }
-        }
-
-        /**
-         * Builds the instance of the {@link NetworkIdentity}.
-         *
-         * @return the built instance of {@link NetworkIdentity}.
-         */
-        @NonNull
-        public NetworkIdentity build() {
-            ensureValidParameters();
-            return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
-                    mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId);
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
deleted file mode 100644
index ad3a958..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.NonNull;
-import android.service.NetworkIdentitySetProto;
-import android.util.proto.ProtoOutputStream;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
- * active on that interface.
- *
- * @hide
- */
-public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
-    private static final int VERSION_INIT = 1;
-    private static final int VERSION_ADD_ROAMING = 2;
-    private static final int VERSION_ADD_NETWORK_ID = 3;
-    private static final int VERSION_ADD_METERED = 4;
-    private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
-    private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
-    private static final int VERSION_ADD_SUB_ID = 7;
-
-    /**
-     * Construct a {@link NetworkIdentitySet} object.
-     */
-    public NetworkIdentitySet() {
-        super();
-    }
-
-    /** @hide */
-    public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) {
-        super(ident);
-    }
-
-    /** @hide */
-    public NetworkIdentitySet(DataInput in) throws IOException {
-        final int version = in.readInt();
-        final int size = in.readInt();
-        for (int i = 0; i < size; i++) {
-            if (version <= VERSION_INIT) {
-                final int ignored = in.readInt();
-            }
-            final int type = in.readInt();
-            final int ratType = in.readInt();
-            final String subscriberId = readOptionalString(in);
-            final String networkId;
-            if (version >= VERSION_ADD_NETWORK_ID) {
-                networkId = readOptionalString(in);
-            } else {
-                networkId = null;
-            }
-            final boolean roaming;
-            if (version >= VERSION_ADD_ROAMING) {
-                roaming = in.readBoolean();
-            } else {
-                roaming = false;
-            }
-
-            final boolean metered;
-            if (version >= VERSION_ADD_METERED) {
-                metered = in.readBoolean();
-            } else {
-                // If this is the old data and the type is mobile, treat it as metered. (Note that
-                // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
-                // used.)
-                metered = (type == TYPE_MOBILE);
-            }
-
-            final boolean defaultNetwork;
-            if (version >= VERSION_ADD_DEFAULT_NETWORK) {
-                defaultNetwork = in.readBoolean();
-            } else {
-                defaultNetwork = true;
-            }
-
-            final int oemNetCapabilities;
-            if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) {
-                oemNetCapabilities = in.readInt();
-            } else {
-                oemNetCapabilities = NetworkIdentity.OEM_NONE;
-            }
-
-            final int subId;
-            if (version >= VERSION_ADD_SUB_ID) {
-                subId = in.readInt();
-            } else {
-                subId = INVALID_SUBSCRIPTION_ID;
-            }
-
-            add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
-                    defaultNetwork, oemNetCapabilities, subId));
-        }
-    }
-
-    /**
-     * Method to serialize this object into a {@code DataOutput}.
-     * @hide
-     */
-    public void writeToStream(DataOutput out) throws IOException {
-        out.writeInt(VERSION_ADD_SUB_ID);
-        out.writeInt(size());
-        for (NetworkIdentity ident : this) {
-            out.writeInt(ident.getType());
-            out.writeInt(ident.getRatType());
-            writeOptionalString(out, ident.getSubscriberId());
-            writeOptionalString(out, ident.getWifiNetworkKey());
-            out.writeBoolean(ident.isRoaming());
-            out.writeBoolean(ident.isMetered());
-            out.writeBoolean(ident.isDefaultNetwork());
-            out.writeInt(ident.getOemManaged());
-            out.writeInt(ident.getSubId());
-        }
-    }
-
-    /**
-     * @return whether any {@link NetworkIdentity} in this set is considered metered.
-     * @hide
-     */
-    public boolean isAnyMemberMetered() {
-        if (isEmpty()) {
-            return false;
-        }
-        for (NetworkIdentity ident : this) {
-            if (ident.isMetered()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @return whether any {@link NetworkIdentity} in this set is considered roaming.
-     * @hide
-     */
-    public boolean isAnyMemberRoaming() {
-        if (isEmpty()) {
-            return false;
-        }
-        for (NetworkIdentity ident : this) {
-            if (ident.isRoaming()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * @return whether any {@link NetworkIdentity} in this set is considered on the default
-     *         network.
-     * @hide
-     */
-    public boolean areAllMembersOnDefaultNetwork() {
-        if (isEmpty()) {
-            return true;
-        }
-        for (NetworkIdentity ident : this) {
-            if (!ident.isDefaultNetwork()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private static void writeOptionalString(DataOutput out, String value) throws IOException {
-        if (value != null) {
-            out.writeByte(1);
-            out.writeUTF(value);
-        } else {
-            out.writeByte(0);
-        }
-    }
-
-    private static String readOptionalString(DataInput in) throws IOException {
-        if (in.readByte() != 0) {
-            return in.readUTF();
-        } else {
-            return null;
-        }
-    }
-
-    public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) {
-        Objects.requireNonNull(left);
-        Objects.requireNonNull(right);
-        if (left.isEmpty()) return -1;
-        if (right.isEmpty()) return 1;
-
-        final NetworkIdentity leftIdent = left.iterator().next();
-        final NetworkIdentity rightIdent = right.iterator().next();
-        return NetworkIdentity.compare(leftIdent, rightIdent);
-    }
-
-    /**
-     * Method to dump this object into proto debug file.
-     * @hide
-     */
-    public void dumpDebug(ProtoOutputStream proto, long tag) {
-        final long start = proto.start(tag);
-
-        for (NetworkIdentity ident : this) {
-            ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES);
-        }
-
-        proto.end(start);
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
deleted file mode 100644
index d3f785a..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.net.module.util.NetworkIdentityUtils;
-
-import java.util.Objects;
-
-/**
- * Snapshot of network state.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class NetworkStateSnapshot implements Parcelable {
-    /** The network associated with this snapshot. */
-    @NonNull
-    private final Network mNetwork;
-
-    /** The {@link NetworkCapabilities} of the network associated with this snapshot. */
-    @NonNull
-    private final NetworkCapabilities mNetworkCapabilities;
-
-    /** The {@link LinkProperties} of the network associated with this snapshot. */
-    @NonNull
-    private final LinkProperties mLinkProperties;
-
-    /**
-     * The Subscriber Id of the network associated with this snapshot. See
-     * {@link android.telephony.TelephonyManager#getSubscriberId()}.
-     */
-    @Nullable
-    private final String mSubscriberId;
-
-    /**
-     * The legacy type of the network associated with this snapshot. See
-     * {@code ConnectivityManager#TYPE_*}.
-     */
-    private final int mLegacyType;
-
-    public NetworkStateSnapshot(@NonNull Network network,
-            @NonNull NetworkCapabilities networkCapabilities,
-            @NonNull LinkProperties linkProperties,
-            @Nullable String subscriberId, int legacyType) {
-        mNetwork = Objects.requireNonNull(network);
-        mNetworkCapabilities = Objects.requireNonNull(networkCapabilities);
-        mLinkProperties = Objects.requireNonNull(linkProperties);
-        mSubscriberId = subscriberId;
-        mLegacyType = legacyType;
-    }
-
-    /** @hide */
-    public NetworkStateSnapshot(@NonNull Parcel in) {
-        mNetwork = in.readParcelable(null);
-        mNetworkCapabilities = in.readParcelable(null);
-        mLinkProperties = in.readParcelable(null);
-        mSubscriberId = in.readString();
-        mLegacyType = in.readInt();
-    }
-
-    /** Get the network associated with this snapshot */
-    @NonNull
-    public Network getNetwork() {
-        return mNetwork;
-    }
-
-    /** Get {@link NetworkCapabilities} of the network associated with this snapshot. */
-    @NonNull
-    public NetworkCapabilities getNetworkCapabilities() {
-        return mNetworkCapabilities;
-    }
-
-    /** Get the {@link LinkProperties} of the network associated with this snapshot. */
-    @NonNull
-    public LinkProperties getLinkProperties() {
-        return mLinkProperties;
-    }
-
-    /**
-     * Get the Subscriber Id of the network associated with this snapshot.
-     * @deprecated Please use #getSubId, which doesn't return personally identifiable
-     * information.
-     */
-    @Deprecated
-    @Nullable
-    public String getSubscriberId() {
-        return mSubscriberId;
-    }
-
-    /** Get the subId of the network associated with this snapshot. */
-    public int getSubId() {
-        if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
-            final NetworkSpecifier spec = mNetworkCapabilities.getNetworkSpecifier();
-            if (spec instanceof TelephonyNetworkSpecifier) {
-                return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
-            }
-        }
-        return INVALID_SUBSCRIPTION_ID;
-    }
-
-
-    /**
-     * Get the legacy type of the network associated with this snapshot.
-     * @return the legacy network type. See {@code ConnectivityManager#TYPE_*}.
-     */
-    public int getLegacyType() {
-        return mLegacyType;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeParcelable(mNetwork, flags);
-        out.writeParcelable(mNetworkCapabilities, flags);
-        out.writeParcelable(mLinkProperties, flags);
-        out.writeString(mSubscriberId);
-        out.writeInt(mLegacyType);
-    }
-
-    @NonNull
-    public static final Creator<NetworkStateSnapshot> CREATOR =
-            new Creator<NetworkStateSnapshot>() {
-        @NonNull
-        @Override
-        public NetworkStateSnapshot createFromParcel(@NonNull Parcel in) {
-            return new NetworkStateSnapshot(in);
-        }
-
-        @NonNull
-        @Override
-        public NetworkStateSnapshot[] newArray(int size) {
-            return new NetworkStateSnapshot[size];
-        }
-    };
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof NetworkStateSnapshot)) return false;
-        NetworkStateSnapshot that = (NetworkStateSnapshot) o;
-        return mLegacyType == that.mLegacyType
-                && Objects.equals(mNetwork, that.mNetwork)
-                && Objects.equals(mNetworkCapabilities, that.mNetworkCapabilities)
-                && Objects.equals(mLinkProperties, that.mLinkProperties)
-                && Objects.equals(mSubscriberId, that.mSubscriberId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mNetwork,
-                mNetworkCapabilities, mLinkProperties, mSubscriberId, mLegacyType);
-    }
-
-    @Override
-    public String toString() {
-        return "NetworkStateSnapshot{"
-                + "network=" + mNetwork
-                + ", networkCapabilities=" + mNetworkCapabilities
-                + ", linkProperties=" + mLinkProperties
-                + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId) + '\''
-                + ", legacyType=" + mLegacyType
-                + '}';
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
deleted file mode 100644
index 06f2a62..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ /dev/null
@@ -1,1834 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.CollectionUtils;
-
-import libcore.util.EmptyArray;
-
-import java.io.CharArrayWriter;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Predicate;
-
-/**
- * Collection of active network statistics. Can contain summary details across
- * all interfaces, or details with per-UID granularity. Internally stores data
- * as a large table, closely matching {@code /proc/} data format. This structure
- * optimizes for rapid in-memory comparison, but consider using
- * {@link NetworkStatsHistory} when persisting.
- *
- * @hide
- */
-// @NotThreadSafe
-@SystemApi
-public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Entry> {
-    private static final String TAG = "NetworkStats";
-
-    /**
-     * {@link #iface} value when interface details unavailable.
-     * @hide
-     */
-    @Nullable public static final String IFACE_ALL = null;
-
-    /**
-     * Virtual network interface for video telephony. This is for VT data usage counting
-     * purpose.
-     */
-    public static final String IFACE_VT = "vt_data0";
-
-    /** {@link #uid} value when UID details unavailable. */
-    public static final int UID_ALL = -1;
-    /** Special UID value for data usage by tethering. */
-    public static final int UID_TETHERING = -5;
-
-    /**
-     * {@link #tag} value matching any tag.
-     * @hide
-     */
-    // TODO: Rename TAG_ALL to TAG_ANY.
-    public static final int TAG_ALL = -1;
-    /** {@link #set} value for all sets combined, not including debug sets. */
-    public static final int SET_ALL = -1;
-    /** {@link #set} value where background data is accounted. */
-    public static final int SET_DEFAULT = 0;
-    /** {@link #set} value where foreground data is accounted. */
-    public static final int SET_FOREGROUND = 1;
-    /**
-     * All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values.
-     * @hide
-     */
-    public static final int SET_DEBUG_START = 1000;
-    /**
-     * Debug {@link #set} value when the VPN stats are moved in.
-     * @hide
-     */
-    public static final int SET_DBG_VPN_IN = 1001;
-    /**
-     * Debug {@link #set} value when the VPN stats are moved out of a vpn UID.
-     * @hide
-     */
-    public static final int SET_DBG_VPN_OUT = 1002;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "SET_" }, value = {
-            SET_ALL,
-            SET_DEFAULT,
-            SET_FOREGROUND,
-    })
-    public @interface State {
-    }
-
-    /**
-     * Include all interfaces when filtering
-     * @hide
-     */
-    public @Nullable static final String[] INTERFACES_ALL = null;
-
-    /** {@link #tag} value for total data across all tags. */
-    // TODO: Rename TAG_NONE to TAG_ALL.
-    public static final int TAG_NONE = 0;
-
-    /** {@link #metered} value to account for all metered states. */
-    public static final int METERED_ALL = -1;
-    /** {@link #metered} value where native, unmetered data is accounted. */
-    public static final int METERED_NO = 0;
-    /** {@link #metered} value where metered data is accounted. */
-    public static final int METERED_YES = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "METERED_" }, value = {
-            METERED_ALL,
-            METERED_NO,
-            METERED_YES
-    })
-    public @interface Meteredness {
-    }
-
-
-    /** {@link #roaming} value to account for all roaming states. */
-    public static final int ROAMING_ALL = -1;
-    /** {@link #roaming} value where native, non-roaming data is accounted. */
-    public static final int ROAMING_NO = 0;
-    /** {@link #roaming} value where roaming data is accounted. */
-    public static final int ROAMING_YES = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "ROAMING_" }, value = {
-            ROAMING_ALL,
-            ROAMING_NO,
-            ROAMING_YES
-    })
-    public @interface Roaming {
-    }
-
-    /** {@link #onDefaultNetwork} value to account for all default network states. */
-    public static final int DEFAULT_NETWORK_ALL = -1;
-    /** {@link #onDefaultNetwork} value to account for usage while not the default network. */
-    public static final int DEFAULT_NETWORK_NO = 0;
-    /** {@link #onDefaultNetwork} value to account for usage while the default network. */
-    public static final int DEFAULT_NETWORK_YES = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = {
-            DEFAULT_NETWORK_ALL,
-            DEFAULT_NETWORK_NO,
-            DEFAULT_NETWORK_YES
-    })
-    public @interface DefaultNetwork {
-    }
-
-    /**
-     * Denotes a request for stats at the interface level.
-     * @hide
-     */
-    public static final int STATS_PER_IFACE = 0;
-    /**
-     * Denotes a request for stats at the interface and UID level.
-     * @hide
-     */
-    public static final int STATS_PER_UID = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "STATS_PER_" }, value = {
-            STATS_PER_IFACE,
-            STATS_PER_UID
-    })
-    public @interface StatsType {
-    }
-
-    private static final String CLATD_INTERFACE_PREFIX = "v4-";
-    // Delta between IPv4 header (20b) and IPv6 header (40b).
-    // Used for correct stats accounting on clatd interfaces.
-    private static final int IPV4V6_HEADER_DELTA = 20;
-
-    // TODO: move fields to "mVariable" notation
-
-    /**
-     * {@link SystemClock#elapsedRealtime()} timestamp in milliseconds when this data was
-     * generated.
-     * It's a timestamps delta when {@link #subtract()},
-     * {@code INetworkStatsSession#getSummaryForAllUid()} methods are used.
-     */
-    private long elapsedRealtime;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int size;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int capacity;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private String[] iface;
-    @UnsupportedAppUsage
-    private int[] uid;
-    @UnsupportedAppUsage
-    private int[] set;
-    @UnsupportedAppUsage
-    private int[] tag;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int[] metered;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int[] roaming;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private int[] defaultNetwork;
-    @UnsupportedAppUsage
-    private long[] rxBytes;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private long[] rxPackets;
-    @UnsupportedAppUsage
-    private long[] txBytes;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private long[] txPackets;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private long[] operations;
-
-    /**
-     * Basic element of network statistics. Contains the number of packets and number of bytes
-     * transferred on both directions in a given set of conditions. See
-     * {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static class Entry {
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public String iface;
-        /** @hide */
-        @UnsupportedAppUsage
-        public int uid;
-        /** @hide */
-        @UnsupportedAppUsage
-        public int set;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public int tag;
-        /**
-         * Note that this is only populated w/ the default value when read from /proc or written
-         * to disk. We merge in the correct value when reporting this value to clients of
-         * getSummary().
-         * @hide
-         */
-        public int metered;
-        /**
-         * Note that this is only populated w/ the default value when read from /proc or written
-         * to disk. We merge in the correct value when reporting this value to clients of
-         * getSummary().
-         * @hide
-         */
-        public int roaming;
-        /**
-         * Note that this is only populated w/ the default value when read from /proc or written
-         * to disk. We merge in the correct value when reporting this value to clients of
-         * getSummary().
-         * @hide
-         */
-        public int defaultNetwork;
-        /** @hide */
-        @UnsupportedAppUsage
-        public long rxBytes;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long rxPackets;
-        /** @hide */
-        @UnsupportedAppUsage
-        public long txBytes;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long txPackets;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long operations;
-
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public Entry() {
-            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
-        }
-
-        /** @hide */
-        public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
-            this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
-                    operations);
-        }
-
-        /** @hide */
-        public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
-                long txBytes, long txPackets, long operations) {
-            this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
-                    rxBytes, rxPackets, txBytes, txPackets, operations);
-        }
-
-        /**
-         * Construct a {@link Entry} object by giving statistics of packet and byte transferred on
-         * both direction, and associated with a set of given conditions.
-         *
-         * @param iface interface name of this {@link Entry}. Or null if not specified.
-         * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
-         *            for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
-         *            counting iface stats.
-         * @param set usage state of this {@link Entry}.
-         * @param tag tag of this {@link Entry}.
-         * @param metered metered state of this {@link Entry}.
-         * @param roaming roaming state of this {@link Entry}.
-         * @param defaultNetwork default network status of this {@link Entry}.
-         * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
-         *                represent the contents of IP packets, including IP headers.
-         * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
-         *                  represent the contents of IP packets, including IP headers.
-         * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
-         *                represent the contents of IP packets, including IP headers.
-         * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
-         *                  represent the contents of IP packets, including IP headers.
-         * @param operations count of network operations performed for this {@link Entry}. This can
-         *                   be used to derive bytes-per-operation.
-         */
-        public Entry(@Nullable String iface, int uid, @State int set, int tag,
-                @Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork,
-                long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
-            this.iface = iface;
-            this.uid = uid;
-            this.set = set;
-            this.tag = tag;
-            this.metered = metered;
-            this.roaming = roaming;
-            this.defaultNetwork = defaultNetwork;
-            this.rxBytes = rxBytes;
-            this.rxPackets = rxPackets;
-            this.txBytes = txBytes;
-            this.txPackets = txPackets;
-            this.operations = operations;
-        }
-
-        /** @hide */
-        public boolean isNegative() {
-            return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
-        }
-
-        /** @hide */
-        public boolean isEmpty() {
-            return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
-                    && operations == 0;
-        }
-
-        /** @hide */
-        public void add(Entry another) {
-            this.rxBytes += another.rxBytes;
-            this.rxPackets += another.rxPackets;
-            this.txBytes += another.txBytes;
-            this.txPackets += another.txPackets;
-            this.operations += another.operations;
-        }
-
-        /**
-         * @return interface name of this entry.
-         * @hide
-         */
-        @Nullable public String getIface() {
-            return iface;
-        }
-
-        /**
-         * @return the uid of this entry.
-         */
-        public int getUid() {
-            return uid;
-        }
-
-        /**
-         * @return the set state of this entry.
-         */
-        @State public int getSet() {
-            return set;
-        }
-
-        /**
-         * @return the tag value of this entry.
-         */
-        public int getTag() {
-            return tag;
-        }
-
-        /**
-         * @return the metered state.
-         */
-        @Meteredness public int getMetered() {
-            return metered;
-        }
-
-        /**
-         * @return the roaming state.
-         */
-        @Roaming public int getRoaming() {
-            return roaming;
-        }
-
-        /**
-         * @return the default network state.
-         */
-        @DefaultNetwork public int getDefaultNetwork() {
-            return defaultNetwork;
-        }
-
-        /**
-         * @return the number of received bytes.
-         */
-        public long getRxBytes() {
-            return rxBytes;
-        }
-
-        /**
-         * @return the number of received packets.
-         */
-        public long getRxPackets() {
-            return rxPackets;
-        }
-
-        /**
-         * @return the number of transmitted bytes.
-         */
-        public long getTxBytes() {
-            return txBytes;
-        }
-
-        /**
-         * @return the number of transmitted packets.
-         */
-        public long getTxPackets() {
-            return txPackets;
-        }
-
-        /**
-         * @return the count of network operations performed for this entry.
-         */
-        public long getOperations() {
-            return operations;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder builder = new StringBuilder();
-            builder.append("iface=").append(iface);
-            builder.append(" uid=").append(uid);
-            builder.append(" set=").append(setToString(set));
-            builder.append(" tag=").append(tagToString(tag));
-            builder.append(" metered=").append(meteredToString(metered));
-            builder.append(" roaming=").append(roamingToString(roaming));
-            builder.append(" defaultNetwork=").append(defaultNetworkToString(defaultNetwork));
-            builder.append(" rxBytes=").append(rxBytes);
-            builder.append(" rxPackets=").append(rxPackets);
-            builder.append(" txBytes=").append(txBytes);
-            builder.append(" txPackets=").append(txPackets);
-            builder.append(" operations=").append(operations);
-            return builder.toString();
-        }
-
-        /** @hide */
-        @Override
-        public boolean equals(@Nullable Object o) {
-            if (o instanceof Entry) {
-                final Entry e = (Entry) o;
-                return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered
-                        && roaming == e.roaming && defaultNetwork == e.defaultNetwork
-                        && rxBytes == e.rxBytes && rxPackets == e.rxPackets
-                        && txBytes == e.txBytes && txPackets == e.txPackets
-                        && operations == e.operations && TextUtils.equals(iface, e.iface);
-            }
-            return false;
-        }
-
-        /** @hide */
-        @Override
-        public int hashCode() {
-            return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
-        }
-    }
-
-    public NetworkStats(long elapsedRealtime, int initialSize) {
-        this.elapsedRealtime = elapsedRealtime;
-        this.size = 0;
-        if (initialSize > 0) {
-            this.capacity = initialSize;
-            this.iface = new String[initialSize];
-            this.uid = new int[initialSize];
-            this.set = new int[initialSize];
-            this.tag = new int[initialSize];
-            this.metered = new int[initialSize];
-            this.roaming = new int[initialSize];
-            this.defaultNetwork = new int[initialSize];
-            this.rxBytes = new long[initialSize];
-            this.rxPackets = new long[initialSize];
-            this.txBytes = new long[initialSize];
-            this.txPackets = new long[initialSize];
-            this.operations = new long[initialSize];
-        } else {
-            // Special case for use by NetworkStatsFactory to start out *really* empty.
-            clear();
-        }
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public NetworkStats(Parcel parcel) {
-        elapsedRealtime = parcel.readLong();
-        size = parcel.readInt();
-        capacity = parcel.readInt();
-        iface = parcel.createStringArray();
-        uid = parcel.createIntArray();
-        set = parcel.createIntArray();
-        tag = parcel.createIntArray();
-        metered = parcel.createIntArray();
-        roaming = parcel.createIntArray();
-        defaultNetwork = parcel.createIntArray();
-        rxBytes = parcel.createLongArray();
-        rxPackets = parcel.createLongArray();
-        txBytes = parcel.createLongArray();
-        txPackets = parcel.createLongArray();
-        operations = parcel.createLongArray();
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeLong(elapsedRealtime);
-        dest.writeInt(size);
-        dest.writeInt(capacity);
-        dest.writeStringArray(iface);
-        dest.writeIntArray(uid);
-        dest.writeIntArray(set);
-        dest.writeIntArray(tag);
-        dest.writeIntArray(metered);
-        dest.writeIntArray(roaming);
-        dest.writeIntArray(defaultNetwork);
-        dest.writeLongArray(rxBytes);
-        dest.writeLongArray(rxPackets);
-        dest.writeLongArray(txBytes);
-        dest.writeLongArray(txPackets);
-        dest.writeLongArray(operations);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public NetworkStats clone() {
-        final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
-        NetworkStats.Entry entry = null;
-        for (int i = 0; i < size; i++) {
-            entry = getValues(i, entry);
-            clone.insertEntry(entry);
-        }
-        return clone;
-    }
-
-    /**
-     * Clear all data stored in this object.
-     * @hide
-     */
-    public void clear() {
-        this.capacity = 0;
-        this.iface = EmptyArray.STRING;
-        this.uid = EmptyArray.INT;
-        this.set = EmptyArray.INT;
-        this.tag = EmptyArray.INT;
-        this.metered = EmptyArray.INT;
-        this.roaming = EmptyArray.INT;
-        this.defaultNetwork = EmptyArray.INT;
-        this.rxBytes = EmptyArray.LONG;
-        this.rxPackets = EmptyArray.LONG;
-        this.txBytes = EmptyArray.LONG;
-        this.txPackets = EmptyArray.LONG;
-        this.operations = EmptyArray.LONG;
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public NetworkStats insertEntry(
-            String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
-        return insertEntry(
-                iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes,
-            long rxPackets, long txBytes, long txPackets, long operations) {
-        return insertEntry(new Entry(
-                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered,
-            int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes,
-            long txPackets, long operations) {
-        return insertEntry(new Entry(
-                iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
-                txBytes, txPackets, operations));
-    }
-
-    /**
-     * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
-     * object can be recycled across multiple calls.
-     * @hide
-     */
-    public NetworkStats insertEntry(Entry entry) {
-        if (size >= capacity) {
-            final int newLength = Math.max(size, 10) * 3 / 2;
-            iface = Arrays.copyOf(iface, newLength);
-            uid = Arrays.copyOf(uid, newLength);
-            set = Arrays.copyOf(set, newLength);
-            tag = Arrays.copyOf(tag, newLength);
-            metered = Arrays.copyOf(metered, newLength);
-            roaming = Arrays.copyOf(roaming, newLength);
-            defaultNetwork = Arrays.copyOf(defaultNetwork, newLength);
-            rxBytes = Arrays.copyOf(rxBytes, newLength);
-            rxPackets = Arrays.copyOf(rxPackets, newLength);
-            txBytes = Arrays.copyOf(txBytes, newLength);
-            txPackets = Arrays.copyOf(txPackets, newLength);
-            operations = Arrays.copyOf(operations, newLength);
-            capacity = newLength;
-        }
-
-        setValues(size, entry);
-        size++;
-
-        return this;
-    }
-
-    private void setValues(int i, Entry entry) {
-        iface[i] = entry.iface;
-        uid[i] = entry.uid;
-        set[i] = entry.set;
-        tag[i] = entry.tag;
-        metered[i] = entry.metered;
-        roaming[i] = entry.roaming;
-        defaultNetwork[i] = entry.defaultNetwork;
-        rxBytes[i] = entry.rxBytes;
-        rxPackets[i] = entry.rxPackets;
-        txBytes[i] = entry.txBytes;
-        txPackets[i] = entry.txPackets;
-        operations[i] = entry.operations;
-    }
-
-    /**
-     * Iterate over Entry objects.
-     *
-     * Return an iterator of this object that will iterate through all contained Entry objects.
-     *
-     * This iterator does not support concurrent modification and makes no guarantee of fail-fast
-     * behavior. If any method that can mutate the contents of this object is called while
-     * iteration is in progress, either inside the loop or in another thread, then behavior is
-     * undefined.
-     * The remove() method is not implemented and will throw UnsupportedOperationException.
-     * @hide
-     */
-    @SystemApi
-    @NonNull public Iterator<Entry> iterator() {
-        return new Iterator<Entry>() {
-            int mIndex = 0;
-
-            @Override
-            public boolean hasNext() {
-                return mIndex < size;
-            }
-
-            @Override
-            public Entry next() {
-                return getValues(mIndex++, null);
-            }
-        };
-    }
-
-    /**
-     * Return specific stats entry.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Entry getValues(int i, @Nullable Entry recycle) {
-        final Entry entry = recycle != null ? recycle : new Entry();
-        entry.iface = iface[i];
-        entry.uid = uid[i];
-        entry.set = set[i];
-        entry.tag = tag[i];
-        entry.metered = metered[i];
-        entry.roaming = roaming[i];
-        entry.defaultNetwork = defaultNetwork[i];
-        entry.rxBytes = rxBytes[i];
-        entry.rxPackets = rxPackets[i];
-        entry.txBytes = txBytes[i];
-        entry.txPackets = txPackets[i];
-        entry.operations = operations[i];
-        return entry;
-    }
-
-    /**
-     * If @{code dest} is not equal to @{code src}, copy entry from index @{code src} to index
-     * @{code dest}.
-     */
-    private void maybeCopyEntry(int dest, int src) {
-        if (dest == src) return;
-        iface[dest] = iface[src];
-        uid[dest] = uid[src];
-        set[dest] = set[src];
-        tag[dest] = tag[src];
-        metered[dest] = metered[src];
-        roaming[dest] = roaming[src];
-        defaultNetwork[dest] = defaultNetwork[src];
-        rxBytes[dest] = rxBytes[src];
-        rxPackets[dest] = rxPackets[src];
-        txBytes[dest] = txBytes[src];
-        txPackets[dest] = txPackets[src];
-        operations[dest] = operations[src];
-    }
-
-    /** @hide */
-    public long getElapsedRealtime() {
-        return elapsedRealtime;
-    }
-
-    /** @hide */
-    public void setElapsedRealtime(long time) {
-        elapsedRealtime = time;
-    }
-
-    /**
-     * Return age of this {@link NetworkStats} object with respect to
-     * {@link SystemClock#elapsedRealtime()}.
-     * @hide
-     */
-    public long getElapsedRealtimeAge() {
-        return SystemClock.elapsedRealtime() - elapsedRealtime;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public int size() {
-        return size;
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public int internalSize() {
-        return capacity;
-    }
-
-    /** @hide */
-    @Deprecated
-    public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
-            long txBytes, long txPackets, long operations) {
-        return combineValues(
-                iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes,
-                txPackets, operations);
-    }
-
-    /** @hide */
-    public NetworkStats combineValues(String iface, int uid, int set, int tag,
-            long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
-        return combineValues(new Entry(
-                iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
-    }
-
-    /**
-     * Combine given values with an existing row, or create a new row if
-     * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
-     * also be used to subtract values from existing rows. This method mutates the referencing
-     * {@link NetworkStats} object.
-     *
-     * @param entry the {@link Entry} to combine.
-     * @return a reference to this mutated {@link NetworkStats} object.
-     * @hide
-     */
-    public @NonNull NetworkStats combineValues(@NonNull Entry entry) {
-        final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
-                entry.roaming, entry.defaultNetwork);
-        if (i == -1) {
-            // only create new entry when positive contribution
-            insertEntry(entry);
-        } else {
-            rxBytes[i] += entry.rxBytes;
-            rxPackets[i] += entry.rxPackets;
-            txBytes[i] += entry.txBytes;
-            txPackets[i] += entry.txPackets;
-            operations[i] += entry.operations;
-        }
-        return this;
-    }
-
-    /**
-     * Add given values with an existing row, or create a new row if
-     * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
-     * also be used to subtract values from existing rows.
-     *
-     * @param entry the {@link Entry} to add.
-     * @return a new constructed {@link NetworkStats} object that contains the result.
-     */
-    public @NonNull NetworkStats addEntry(@NonNull Entry entry) {
-        return this.clone().combineValues(entry);
-    }
-
-    /**
-     * Add the given {@link NetworkStats} objects.
-     *
-     * @return the sum of two objects.
-     */
-    public @NonNull NetworkStats add(@NonNull NetworkStats another) {
-        final NetworkStats ret = this.clone();
-        ret.combineAllValues(another);
-        return ret;
-    }
-
-    /**
-     * Combine all values from another {@link NetworkStats} into this object.
-     * @hide
-     */
-    public void combineAllValues(@NonNull NetworkStats another) {
-        NetworkStats.Entry entry = null;
-        for (int i = 0; i < another.size; i++) {
-            entry = another.getValues(i, entry);
-            combineValues(entry);
-        }
-    }
-
-    /**
-     * Find first stats index that matches the requested parameters.
-     * @hide
-     */
-    public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
-            int defaultNetwork) {
-        for (int i = 0; i < size; i++) {
-            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
-                    && metered == this.metered[i] && roaming == this.roaming[i]
-                    && defaultNetwork == this.defaultNetwork[i]
-                    && Objects.equals(iface, this.iface[i])) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Find first stats index that matches the requested parameters, starting
-     * search around the hinted index as an optimization.
-     * @hide
-     */
-    @VisibleForTesting
-    public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
-            int defaultNetwork, int hintIndex) {
-        for (int offset = 0; offset < size; offset++) {
-            final int halfOffset = offset / 2;
-
-            // search outwards from hint index, alternating forward and backward
-            final int i;
-            if (offset % 2 == 0) {
-                i = (hintIndex + halfOffset) % size;
-            } else {
-                i = (size + hintIndex - halfOffset - 1) % size;
-            }
-
-            if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
-                    && metered == this.metered[i] && roaming == this.roaming[i]
-                    && defaultNetwork == this.defaultNetwork[i]
-                    && Objects.equals(iface, this.iface[i])) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Splice in {@link #operations} from the given {@link NetworkStats} based
-     * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
-     * since operation counts are at data layer.
-     * @hide
-     */
-    public void spliceOperationsFrom(NetworkStats stats) {
-        for (int i = 0; i < size; i++) {
-            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i],
-                    defaultNetwork[i]);
-            if (j == -1) {
-                operations[i] = 0;
-            } else {
-                operations[i] = stats.operations[j];
-            }
-        }
-    }
-
-    /**
-     * Return list of unique interfaces known by this data structure.
-     * @hide
-     */
-    public String[] getUniqueIfaces() {
-        final HashSet<String> ifaces = new HashSet<String>();
-        for (String iface : this.iface) {
-            if (iface != IFACE_ALL) {
-                ifaces.add(iface);
-            }
-        }
-        return ifaces.toArray(new String[ifaces.size()]);
-    }
-
-    /**
-     * Return list of unique UIDs known by this data structure.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public int[] getUniqueUids() {
-        final SparseBooleanArray uids = new SparseBooleanArray();
-        for (int uid : this.uid) {
-            uids.put(uid, true);
-        }
-
-        final int size = uids.size();
-        final int[] result = new int[size];
-        for (int i = 0; i < size; i++) {
-            result[i] = uids.keyAt(i);
-        }
-        return result;
-    }
-
-    /**
-     * Return total bytes represented by this snapshot object, usually used when
-     * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public long getTotalBytes() {
-        final Entry entry = getTotal(null);
-        return entry.rxBytes + entry.txBytes;
-    }
-
-    /**
-     * Return total of all fields represented by this snapshot object.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Entry getTotal(Entry recycle) {
-        return getTotal(recycle, null, UID_ALL, false);
-    }
-
-    /**
-     * Return total of all fields represented by this snapshot object matching
-     * the requested {@link #uid}.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Entry getTotal(Entry recycle, int limitUid) {
-        return getTotal(recycle, null, limitUid, false);
-    }
-
-    /**
-     * Return total of all fields represented by this snapshot object matching
-     * the requested {@link #iface}.
-     * @hide
-     */
-    public Entry getTotal(Entry recycle, HashSet<String> limitIface) {
-        return getTotal(recycle, limitIface, UID_ALL, false);
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public Entry getTotalIncludingTags(Entry recycle) {
-        return getTotal(recycle, null, UID_ALL, true);
-    }
-
-    /**
-     * Return total of all fields represented by this snapshot object matching
-     * the requested {@link #iface} and {@link #uid}.
-     *
-     * @param limitIface Set of {@link #iface} to include in total; or {@code
-     *            null} to include all ifaces.
-     */
-    private Entry getTotal(
-            Entry recycle, HashSet<String> limitIface, int limitUid, boolean includeTags) {
-        final Entry entry = recycle != null ? recycle : new Entry();
-
-        entry.iface = IFACE_ALL;
-        entry.uid = limitUid;
-        entry.set = SET_ALL;
-        entry.tag = TAG_NONE;
-        entry.metered = METERED_ALL;
-        entry.roaming = ROAMING_ALL;
-        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
-        entry.rxBytes = 0;
-        entry.rxPackets = 0;
-        entry.txBytes = 0;
-        entry.txPackets = 0;
-        entry.operations = 0;
-
-        for (int i = 0; i < size; i++) {
-            final boolean matchesUid = (limitUid == UID_ALL) || (limitUid == uid[i]);
-            final boolean matchesIface = (limitIface == null) || (limitIface.contains(iface[i]));
-
-            if (matchesUid && matchesIface) {
-                // skip specific tags, since already counted in TAG_NONE
-                if (tag[i] != TAG_NONE && !includeTags) continue;
-
-                entry.rxBytes += rxBytes[i];
-                entry.rxPackets += rxPackets[i];
-                entry.txBytes += txBytes[i];
-                entry.txPackets += txPackets[i];
-                entry.operations += operations[i];
-            }
-        }
-        return entry;
-    }
-
-    /**
-     * Fast path for battery stats.
-     * @hide
-     */
-    public long getTotalPackets() {
-        long total = 0;
-        for (int i = size-1; i >= 0; i--) {
-            total += rxPackets[i] + txPackets[i];
-        }
-        return total;
-    }
-
-    /**
-     * Subtract the given {@link NetworkStats}, effectively leaving the delta
-     * between two snapshots in time. Assumes that statistics rows collect over
-     * time, and that none of them have disappeared. This method does not mutate
-     * the referencing object.
-     *
-     * @return the delta between two objects.
-     */
-    public @NonNull NetworkStats subtract(@NonNull NetworkStats right) {
-        return subtract(this, right, null, null);
-    }
-
-    /**
-     * Subtract the two given {@link NetworkStats} objects, returning the delta
-     * between two snapshots in time. Assumes that statistics rows collect over
-     * time, and that none of them have disappeared.
-     * <p>
-     * If counters have rolled backwards, they are clamped to {@code 0} and
-     * reported to the given {@link NonMonotonicObserver}.
-     * @hide
-     */
-    public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
-            NonMonotonicObserver<C> observer, C cookie) {
-        return subtract(left, right, observer, cookie, null);
-    }
-
-    /**
-     * Subtract the two given {@link NetworkStats} objects, returning the delta
-     * between two snapshots in time. Assumes that statistics rows collect over
-     * time, and that none of them have disappeared.
-     * <p>
-     * If counters have rolled backwards, they are clamped to {@code 0} and
-     * reported to the given {@link NonMonotonicObserver}.
-     * <p>
-     * If <var>recycle</var> is supplied, this NetworkStats object will be
-     * reused (and returned) as the result if it is large enough to contain
-     * the data.
-     * @hide
-     */
-    public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
-            NonMonotonicObserver<C> observer, C cookie, NetworkStats recycle) {
-        long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime;
-        if (deltaRealtime < 0) {
-            if (observer != null) {
-                observer.foundNonMonotonic(left, -1, right, -1, cookie);
-            }
-            deltaRealtime = 0;
-        }
-
-        // result will have our rows, and elapsed time between snapshots
-        final Entry entry = new Entry();
-        final NetworkStats result;
-        if (recycle != null && recycle.capacity >= left.size) {
-            result = recycle;
-            result.size = 0;
-            result.elapsedRealtime = deltaRealtime;
-        } else {
-            result = new NetworkStats(deltaRealtime, left.size);
-        }
-        for (int i = 0; i < left.size; i++) {
-            entry.iface = left.iface[i];
-            entry.uid = left.uid[i];
-            entry.set = left.set[i];
-            entry.tag = left.tag[i];
-            entry.metered = left.metered[i];
-            entry.roaming = left.roaming[i];
-            entry.defaultNetwork = left.defaultNetwork[i];
-            entry.rxBytes = left.rxBytes[i];
-            entry.rxPackets = left.rxPackets[i];
-            entry.txBytes = left.txBytes[i];
-            entry.txPackets = left.txPackets[i];
-            entry.operations = left.operations[i];
-
-            // find remote row that matches, and subtract
-            final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
-                    entry.metered, entry.roaming, entry.defaultNetwork, i);
-            if (j != -1) {
-                // Found matching row, subtract remote value.
-                entry.rxBytes -= right.rxBytes[j];
-                entry.rxPackets -= right.rxPackets[j];
-                entry.txBytes -= right.txBytes[j];
-                entry.txPackets -= right.txPackets[j];
-                entry.operations -= right.operations[j];
-            }
-
-            if (entry.isNegative()) {
-                if (observer != null) {
-                    observer.foundNonMonotonic(left, i, right, j, cookie);
-                }
-                entry.rxBytes = Math.max(entry.rxBytes, 0);
-                entry.rxPackets = Math.max(entry.rxPackets, 0);
-                entry.txBytes = Math.max(entry.txBytes, 0);
-                entry.txPackets = Math.max(entry.txPackets, 0);
-                entry.operations = Math.max(entry.operations, 0);
-            }
-
-            result.insertEntry(entry);
-        }
-
-        return result;
-    }
-
-    /**
-     * Calculate and apply adjustments to captured statistics for 464xlat traffic.
-     *
-     * <p>This mutates stacked traffic stats, to account for IPv4/IPv6 header size difference.
-     *
-     * <p>UID stats, which are only accounted on the stacked interface, need to be increased
-     * by 20 bytes/packet to account for translation overhead.
-     *
-     * <p>The potential additional overhead of 8 bytes/packet for ip fragments is ignored.
-     *
-     * <p>Interface stats need to sum traffic on both stacked and base interface because:
-     *   - eBPF offloaded packets appear only on the stacked interface
-     *   - Non-offloaded ingress packets appear only on the stacked interface
-     *     (due to iptables raw PREROUTING drop rules)
-     *   - Non-offloaded egress packets appear only on the stacked interface
-     *     (due to ignoring traffic from clat daemon by uid match)
-     * (and of course the 20 bytes/packet overhead needs to be applied to stacked interface stats)
-     *
-     * <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only
-     * {@code ConcurrentHashMap}
-     * @param baseTraffic Traffic on the base interfaces. Will be mutated.
-     * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
-     * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
-     * @hide
-     */
-    public static void apply464xlatAdjustments(NetworkStats baseTraffic,
-            NetworkStats stackedTraffic, Map<String, String> stackedIfaces) {
-        // For recycling
-        Entry entry = null;
-        for (int i = 0; i < stackedTraffic.size; i++) {
-            entry = stackedTraffic.getValues(i, entry);
-            if (entry == null) continue;
-            if (entry.iface == null) continue;
-            if (!entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) continue;
-
-            // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet
-            // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after
-            // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes
-            // difference for all packets (http://b/12249687, http:/b/33681750).
-            //
-            // Note: this doesn't account for LRO/GRO/GSO/TSO (ie. >mtu) traffic correctly, nor
-            // does it correctly account for the 8 extra bytes in the IPv6 fragmentation header.
-            //
-            // While the ebpf code path does try to simulate proper post segmentation packet
-            // counts, we have nothing of the sort of xt_qtaguid stats.
-            entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA;
-            entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA;
-            stackedTraffic.setValues(i, entry);
-        }
-    }
-
-    /**
-     * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice.
-     *
-     * <p>This mutates the object this method is called on. Equivalent to calling
-     * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as
-     * base and stacked traffic.
-     * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
-     * @hide
-     */
-    public void apply464xlatAdjustments(Map<String, String> stackedIfaces) {
-        apply464xlatAdjustments(this, this, stackedIfaces);
-    }
-
-    /**
-     * Return total statistics grouped by {@link #iface}; doesn't mutate the
-     * original structure.
-     * @hide
-     */
-    public NetworkStats groupedByIface() {
-        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
-        final Entry entry = new Entry();
-        entry.uid = UID_ALL;
-        entry.set = SET_ALL;
-        entry.tag = TAG_NONE;
-        entry.metered = METERED_ALL;
-        entry.roaming = ROAMING_ALL;
-        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
-        entry.operations = 0L;
-
-        for (int i = 0; i < size; i++) {
-            // skip specific tags, since already counted in TAG_NONE
-            if (tag[i] != TAG_NONE) continue;
-
-            entry.iface = iface[i];
-            entry.rxBytes = rxBytes[i];
-            entry.rxPackets = rxPackets[i];
-            entry.txBytes = txBytes[i];
-            entry.txPackets = txPackets[i];
-            stats.combineValues(entry);
-        }
-
-        return stats;
-    }
-
-    /**
-     * Return total statistics grouped by {@link #uid}; doesn't mutate the
-     * original structure.
-     * @hide
-     */
-    public NetworkStats groupedByUid() {
-        final NetworkStats stats = new NetworkStats(elapsedRealtime, 10);
-
-        final Entry entry = new Entry();
-        entry.iface = IFACE_ALL;
-        entry.set = SET_ALL;
-        entry.tag = TAG_NONE;
-        entry.metered = METERED_ALL;
-        entry.roaming = ROAMING_ALL;
-        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
-
-        for (int i = 0; i < size; i++) {
-            // skip specific tags, since already counted in TAG_NONE
-            if (tag[i] != TAG_NONE) continue;
-
-            entry.uid = uid[i];
-            entry.rxBytes = rxBytes[i];
-            entry.rxPackets = rxPackets[i];
-            entry.txBytes = txBytes[i];
-            entry.txPackets = txPackets[i];
-            entry.operations = operations[i];
-            stats.combineValues(entry);
-        }
-
-        return stats;
-    }
-
-    /**
-     * Remove all rows that match one of specified UIDs.
-     * This mutates the original structure in place.
-     * @hide
-     */
-    public void removeUids(int[] uids) {
-        filter(e -> !CollectionUtils.contains(uids, e.uid));
-    }
-
-    /**
-     * Remove all rows that match one of specified UIDs.
-     * @return the result object.
-     * @hide
-     */
-    @NonNull
-    public NetworkStats removeEmptyEntries() {
-        final NetworkStats ret = this.clone();
-        ret.filter(e -> e.rxBytes != 0 || e.rxPackets != 0 || e.txBytes != 0 || e.txPackets != 0
-                || e.operations != 0);
-        return ret;
-    }
-
-    /**
-     * Only keep entries that match all specified filters.
-     *
-     * <p>This mutates the original structure in place. After this method is called,
-     * size is the number of matching entries, and capacity is the previous capacity.
-     * @param limitUid UID to filter for, or {@link #UID_ALL}.
-     * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}.
-     * @param limitTag Tag to filter for, or {@link #TAG_ALL}.
-     * @hide
-     */
-    public void filter(int limitUid, String[] limitIfaces, int limitTag) {
-        if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
-            return;
-        }
-        filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
-                && (limitTag == TAG_ALL || limitTag == e.tag)
-                && (limitIfaces == INTERFACES_ALL
-                    || CollectionUtils.contains(limitIfaces, e.iface)));
-    }
-
-    /**
-     * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
-     *
-     * <p>This mutates the original structure in place.
-     * @hide
-     */
-    public void filterDebugEntries() {
-        filter(e -> e.set < SET_DEBUG_START);
-    }
-
-    private void filter(Predicate<Entry> predicate) {
-        Entry entry = new Entry();
-        int nextOutputEntry = 0;
-        for (int i = 0; i < size; i++) {
-            entry = getValues(i, entry);
-            if (predicate.test(entry)) {
-                if (nextOutputEntry != i) {
-                    setValues(nextOutputEntry, entry);
-                }
-                nextOutputEntry++;
-            }
-        }
-        size = nextOutputEntry;
-    }
-
-    /** @hide */
-    public void dump(String prefix, PrintWriter pw) {
-        pw.print(prefix);
-        pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
-        for (int i = 0; i < size; i++) {
-            pw.print(prefix);
-            pw.print("  ["); pw.print(i); pw.print("]");
-            pw.print(" iface="); pw.print(iface[i]);
-            pw.print(" uid="); pw.print(uid[i]);
-            pw.print(" set="); pw.print(setToString(set[i]));
-            pw.print(" tag="); pw.print(tagToString(tag[i]));
-            pw.print(" metered="); pw.print(meteredToString(metered[i]));
-            pw.print(" roaming="); pw.print(roamingToString(roaming[i]));
-            pw.print(" defaultNetwork="); pw.print(defaultNetworkToString(defaultNetwork[i]));
-            pw.print(" rxBytes="); pw.print(rxBytes[i]);
-            pw.print(" rxPackets="); pw.print(rxPackets[i]);
-            pw.print(" txBytes="); pw.print(txBytes[i]);
-            pw.print(" txPackets="); pw.print(txPackets[i]);
-            pw.print(" operations="); pw.println(operations[i]);
-        }
-    }
-
-    /**
-     * Return text description of {@link #set} value.
-     * @hide
-     */
-    public static String setToString(int set) {
-        switch (set) {
-            case SET_ALL:
-                return "ALL";
-            case SET_DEFAULT:
-                return "DEFAULT";
-            case SET_FOREGROUND:
-                return "FOREGROUND";
-            case SET_DBG_VPN_IN:
-                return "DBG_VPN_IN";
-            case SET_DBG_VPN_OUT:
-                return "DBG_VPN_OUT";
-            default:
-                return "UNKNOWN";
-        }
-    }
-
-    /**
-     * Return text description of {@link #set} value.
-     * @hide
-     */
-    public static String setToCheckinString(int set) {
-        switch (set) {
-            case SET_ALL:
-                return "all";
-            case SET_DEFAULT:
-                return "def";
-            case SET_FOREGROUND:
-                return "fg";
-            case SET_DBG_VPN_IN:
-                return "vpnin";
-            case SET_DBG_VPN_OUT:
-                return "vpnout";
-            default:
-                return "unk";
-        }
-    }
-
-    /**
-     * @return true if the querySet matches the dataSet.
-     * @hide
-     */
-    public static boolean setMatches(int querySet, int dataSet) {
-        if (querySet == dataSet) {
-            return true;
-        }
-        // SET_ALL matches all non-debugging sets.
-        return querySet == SET_ALL && dataSet < SET_DEBUG_START;
-    }
-
-    /**
-     * Return text description of {@link #tag} value.
-     * @hide
-     */
-    public static String tagToString(int tag) {
-        return "0x" + Integer.toHexString(tag);
-    }
-
-    /**
-     * Return text description of {@link #metered} value.
-     * @hide
-     */
-    public static String meteredToString(int metered) {
-        switch (metered) {
-            case METERED_ALL:
-                return "ALL";
-            case METERED_NO:
-                return "NO";
-            case METERED_YES:
-                return "YES";
-            default:
-                return "UNKNOWN";
-        }
-    }
-
-    /**
-     * Return text description of {@link #roaming} value.
-     * @hide
-     */
-    public static String roamingToString(int roaming) {
-        switch (roaming) {
-            case ROAMING_ALL:
-                return "ALL";
-            case ROAMING_NO:
-                return "NO";
-            case ROAMING_YES:
-                return "YES";
-            default:
-                return "UNKNOWN";
-        }
-    }
-
-    /**
-     * Return text description of {@link #defaultNetwork} value.
-     * @hide
-     */
-    public static String defaultNetworkToString(int defaultNetwork) {
-        switch (defaultNetwork) {
-            case DEFAULT_NETWORK_ALL:
-                return "ALL";
-            case DEFAULT_NETWORK_NO:
-                return "NO";
-            case DEFAULT_NETWORK_YES:
-                return "YES";
-            default:
-                return "UNKNOWN";
-        }
-    }
-
-    /** @hide */
-    @Override
-    public String toString() {
-        final CharArrayWriter writer = new CharArrayWriter();
-        dump("", new PrintWriter(writer));
-        return writer.toString();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @NonNull Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
-        @Override
-        public NetworkStats createFromParcel(Parcel in) {
-            return new NetworkStats(in);
-        }
-
-        @Override
-        public NetworkStats[] newArray(int size) {
-            return new NetworkStats[size];
-        }
-    };
-
-    /** @hide */
-    public interface NonMonotonicObserver<C> {
-        public void foundNonMonotonic(
-                NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
-        public void foundNonMonotonic(
-                NetworkStats stats, int statsIndex, C cookie);
-    }
-
-    /**
-     * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
-     *
-     * <p>This method should only be called on delta NetworkStats. Do not call this method on a
-     * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
-     * over time.
-     *
-     * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
-     *
-     * @param tunUid uid of the VPN application
-     * @param tunIface iface of the vpn tunnel
-     * @param underlyingIfaces underlying network ifaces used by the VPN application
-     * @hide
-     */
-    public void migrateTun(int tunUid, @NonNull String tunIface,
-            @NonNull List<String> underlyingIfaces) {
-        // Combined usage by all apps using VPN.
-        final Entry tunIfaceTotal = new Entry();
-        // Usage by VPN, grouped by its {@code underlyingIfaces}.
-        final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.size()];
-        // Usage by VPN, summed across all its {@code underlyingIfaces}.
-        final Entry underlyingIfacesTotal = new Entry();
-
-        for (int i = 0; i < perInterfaceTotal.length; i++) {
-            perInterfaceTotal[i] = new Entry();
-        }
-
-        tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
-                underlyingIfacesTotal);
-
-        // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
-        // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
-        // Negative stats should be avoided.
-        final Entry[] moved =
-                addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
-                        perInterfaceTotal, underlyingIfacesTotal);
-        deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
-    }
-
-    /**
-     * Initializes the data used by the migrateTun() method.
-     *
-     * <p>This is the first pass iteration which does the following work:
-     *
-     * <ul>
-     *   <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
-     *       background).
-     *   <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
-     * </ul>
-     *
-     * @param tunUid uid of the VPN application
-     * @param tunIface iface of the vpn tunnel
-     * @param underlyingIfaces underlying network ifaces used by the VPN application
-     * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
-     * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
-     *     underlyingIfaces}
-     * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
-     *     {@code underlyingIfaces}
-     */
-    private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
-            @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
-            @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
-        final Entry recycle = new Entry();
-        for (int i = 0; i < size; i++) {
-            getValues(i, recycle);
-            if (recycle.uid == UID_ALL) {
-                throw new IllegalStateException(
-                        "Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
-            }
-            if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
-                throw new IllegalStateException(
-                        "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
-            }
-            if (recycle.tag != TAG_NONE) {
-                // TODO(b/123666283): Take all tags for tunUid into account.
-                continue;
-            }
-
-            if (tunUid == Process.SYSTEM_UID) {
-                // Kernel-based VPN or VCN, traffic sent by apps on the VPN/VCN network
-                //
-                // Since the data is not UID-accounted on underlying networks, just use VPN/VCN
-                // network usage as ground truth. Encrypted traffic on the underlying networks will
-                // never be processed here because encrypted traffic on the underlying interfaces
-                // is not present in UID stats, and this method is only called on UID stats.
-                if (tunIface.equals(recycle.iface)) {
-                    tunIfaceTotal.add(recycle);
-                    underlyingIfacesTotal.add(recycle);
-
-                    // In steady state, there should always be one network, but edge cases may
-                    // result in the network being null (network lost), and thus no underlying
-                    // ifaces is possible.
-                    if (perInterfaceTotal.length > 0) {
-                        // While platform VPNs and VCNs have exactly one underlying network, that
-                        // network may have multiple interfaces (eg for 464xlat). This layer does
-                        // not have the required information to identify which of the interfaces
-                        // were used. Select "any" of the interfaces. Since overhead is already
-                        // lost, this number is an approximation anyways.
-                        perInterfaceTotal[0].add(recycle);
-                    }
-                }
-            } else if (recycle.uid == tunUid) {
-                // VpnService VPN, traffic sent by the VPN app over underlying networks
-                for (int j = 0; j < underlyingIfaces.size(); j++) {
-                    if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) {
-                        perInterfaceTotal[j].add(recycle);
-                        underlyingIfacesTotal.add(recycle);
-                        break;
-                    }
-                }
-            } else if (tunIface.equals(recycle.iface)) {
-                // VpnService VPN; traffic sent by apps on the VPN network
-                tunIfaceTotal.add(recycle);
-            }
-        }
-    }
-
-    /**
-     * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
-     * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
-     *
-     * @param tunUid uid of the VPN application
-     * @param tunIface iface of the vpn tunnel
-     * @param underlyingIfaces underlying network ifaces used by the VPN application
-     * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
-     * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
-     * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
-     *     underlyingIfaces}
-     */
-    private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
-            @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
-            @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
-        // Traffic that should be moved off of each underlying interface for tunUid (see
-        // deductTrafficFromVpnApp below).
-        final Entry[] moved = new Entry[underlyingIfaces.size()];
-        for (int i = 0; i < underlyingIfaces.size(); i++) {
-            moved[i] = new Entry();
-        }
-
-        final Entry tmpEntry = new Entry();
-        final int origSize = size;
-        for (int i = 0; i < origSize; i++) {
-            if (!Objects.equals(iface[i], tunIface)) {
-                // Consider only entries that go onto the VPN interface.
-                continue;
-            }
-
-            if (uid[i] == tunUid && tunUid != Process.SYSTEM_UID) {
-                // Exclude VPN app from the redistribution, as it can choose to create packet
-                // streams by writing to itself.
-                //
-                // However, for platform VPNs, do not exclude the system's usage of the VPN network,
-                // since it is never local-only, and never double counted
-                continue;
-            }
-            tmpEntry.uid = uid[i];
-            tmpEntry.tag = tag[i];
-            tmpEntry.metered = metered[i];
-            tmpEntry.roaming = roaming[i];
-            tmpEntry.defaultNetwork = defaultNetwork[i];
-
-            // In a first pass, compute this entry's total share of data across all
-            // underlyingIfaces. This is computed on the basis of the share of this entry's usage
-            // over tunIface.
-            // TODO: Consider refactoring first pass into a separate helper method.
-            long totalRxBytes = 0;
-            if (tunIfaceTotal.rxBytes > 0) {
-                // Note - The multiplication below should not overflow since NetworkStatsService
-                // processes this every time device has transmitted/received amount equivalent to
-                // global threshold alert (~ 2MB) across all interfaces.
-                final long rxBytesAcrossUnderlyingIfaces =
-                        multiplySafeByRational(underlyingIfacesTotal.rxBytes,
-                                rxBytes[i], tunIfaceTotal.rxBytes);
-                // app must not be blamed for more than it consumed on tunIface
-                totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
-            }
-            long totalRxPackets = 0;
-            if (tunIfaceTotal.rxPackets > 0) {
-                final long rxPacketsAcrossUnderlyingIfaces =
-                        multiplySafeByRational(underlyingIfacesTotal.rxPackets,
-                                rxPackets[i], tunIfaceTotal.rxPackets);
-                totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
-            }
-            long totalTxBytes = 0;
-            if (tunIfaceTotal.txBytes > 0) {
-                final long txBytesAcrossUnderlyingIfaces =
-                        multiplySafeByRational(underlyingIfacesTotal.txBytes,
-                                txBytes[i], tunIfaceTotal.txBytes);
-                totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
-            }
-            long totalTxPackets = 0;
-            if (tunIfaceTotal.txPackets > 0) {
-                final long txPacketsAcrossUnderlyingIfaces =
-                        multiplySafeByRational(underlyingIfacesTotal.txPackets,
-                                txPackets[i], tunIfaceTotal.txPackets);
-                totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
-            }
-            long totalOperations = 0;
-            if (tunIfaceTotal.operations > 0) {
-                final long operationsAcrossUnderlyingIfaces =
-                        multiplySafeByRational(underlyingIfacesTotal.operations,
-                                operations[i], tunIfaceTotal.operations);
-                totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
-            }
-            // In a second pass, distribute these values across interfaces in the proportion that
-            // each interface represents of the total traffic of the underlying interfaces.
-            for (int j = 0; j < underlyingIfaces.size(); j++) {
-                tmpEntry.iface = underlyingIfaces.get(j);
-                tmpEntry.rxBytes = 0;
-                // Reset 'set' to correct value since it gets updated when adding debug info below.
-                tmpEntry.set = set[i];
-                if (underlyingIfacesTotal.rxBytes > 0) {
-                    tmpEntry.rxBytes =
-                            multiplySafeByRational(totalRxBytes,
-                                    perInterfaceTotal[j].rxBytes,
-                                    underlyingIfacesTotal.rxBytes);
-                }
-                tmpEntry.rxPackets = 0;
-                if (underlyingIfacesTotal.rxPackets > 0) {
-                    tmpEntry.rxPackets =
-                            multiplySafeByRational(totalRxPackets,
-                                    perInterfaceTotal[j].rxPackets,
-                                    underlyingIfacesTotal.rxPackets);
-                }
-                tmpEntry.txBytes = 0;
-                if (underlyingIfacesTotal.txBytes > 0) {
-                    tmpEntry.txBytes =
-                            multiplySafeByRational(totalTxBytes,
-                                    perInterfaceTotal[j].txBytes,
-                                    underlyingIfacesTotal.txBytes);
-                }
-                tmpEntry.txPackets = 0;
-                if (underlyingIfacesTotal.txPackets > 0) {
-                    tmpEntry.txPackets =
-                            multiplySafeByRational(totalTxPackets,
-                                    perInterfaceTotal[j].txPackets,
-                                    underlyingIfacesTotal.txPackets);
-                }
-                tmpEntry.operations = 0;
-                if (underlyingIfacesTotal.operations > 0) {
-                    tmpEntry.operations =
-                            multiplySafeByRational(totalOperations,
-                                    perInterfaceTotal[j].operations,
-                                    underlyingIfacesTotal.operations);
-                }
-                // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
-                // interface. Add that data usage to this object.
-                combineValues(tmpEntry);
-                if (tag[i] == TAG_NONE) {
-                    // Add the migrated data to moved so it is deducted from the VPN app later.
-                    moved[j].add(tmpEntry);
-                    // Add debug info
-                    tmpEntry.set = SET_DBG_VPN_IN;
-                    combineValues(tmpEntry);
-                }
-            }
-        }
-        return moved;
-    }
-
-    private void deductTrafficFromVpnApp(
-            int tunUid,
-            @NonNull List<String> underlyingIfaces,
-            @NonNull Entry[] moved) {
-        if (tunUid == Process.SYSTEM_UID) {
-            // No traffic recorded on a per-UID basis for in-kernel VPN/VCNs over underlying
-            // networks; thus no traffic to deduct.
-            return;
-        }
-
-        for (int i = 0; i < underlyingIfaces.size(); i++) {
-            moved[i].uid = tunUid;
-            // Add debug info
-            moved[i].set = SET_DBG_VPN_OUT;
-            moved[i].tag = TAG_NONE;
-            moved[i].iface = underlyingIfaces.get(i);
-            moved[i].metered = METERED_ALL;
-            moved[i].roaming = ROAMING_ALL;
-            moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
-            combineValues(moved[i]);
-
-            // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
-            // the TAG_NONE traffic.
-            //
-            // Relies on the fact that the underlying traffic only has state ROAMING_NO and
-            // METERED_NO, which should be the case as it comes directly from the /proc file.
-            // We only blend in the roaming data after applying these adjustments, by checking the
-            // NetworkIdentity of the underlying iface.
-            final int idxVpnBackground = findIndex(underlyingIfaces.get(i), tunUid, SET_DEFAULT,
-                            TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
-            if (idxVpnBackground != -1) {
-                // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
-                // from foreground usage.
-                tunSubtract(idxVpnBackground, this, moved[i]);
-            }
-
-            final int idxVpnForeground = findIndex(underlyingIfaces.get(i), tunUid, SET_FOREGROUND,
-                            TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
-            if (idxVpnForeground != -1) {
-                tunSubtract(idxVpnForeground, this, moved[i]);
-            }
-        }
-    }
-
-    private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
-        long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
-        left.rxBytes[i] -= rxBytes;
-        right.rxBytes -= rxBytes;
-
-        long rxPackets = Math.min(left.rxPackets[i], right.rxPackets);
-        left.rxPackets[i] -= rxPackets;
-        right.rxPackets -= rxPackets;
-
-        long txBytes = Math.min(left.txBytes[i], right.txBytes);
-        left.txBytes[i] -= txBytes;
-        right.txBytes -= txBytes;
-
-        long txPackets = Math.min(left.txPackets[i], right.txPackets);
-        left.txPackets[i] -= txPackets;
-        right.txPackets -= txPackets;
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
deleted file mode 100644
index b64fbdb..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.TrafficStats.UID_TETHERING;
-
-import android.Manifest;
-import android.annotation.IntDef;
-import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Process;
-import android.os.UserHandle;
-import android.telephony.TelephonyManager;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Utility methods for controlling access to network stats APIs.
- *
- * @hide
- */
-public final class NetworkStatsAccess {
-    private NetworkStatsAccess() {}
-
-    /**
-     * Represents an access level for the network usage history and statistics APIs.
-     *
-     * <p>Access levels are in increasing order; that is, it is reasonable to check access by
-     * verifying that the caller's access level is at least the minimum required level.
-     */
-    @IntDef({
-            Level.DEFAULT,
-            Level.USER,
-            Level.DEVICESUMMARY,
-            Level.DEVICE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Level {
-        /**
-         * Default, unprivileged access level.
-         *
-         * <p>Can only access usage for one's own UID.
-         *
-         * <p>Every app will have at least this access level.
-         */
-        int DEFAULT = 0;
-
-        /**
-         * Access level for apps which can access usage for any app running in the same user.
-         *
-         * <p>Granted to:
-         * <ul>
-         * <li>Profile owners.
-         * </ul>
-         */
-        int USER = 1;
-
-        /**
-         * Access level for apps which can access usage summary of device. Device summary includes
-         * usage by apps running in any profiles/users, however this access level does not
-         * allow querying usage of individual apps running in other profiles/users.
-         *
-         * <p>Granted to:
-         * <ul>
-         * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
-         * so it is not necessarily sufficient to declare this in the manifest.
-         * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
-         * </ul>
-         */
-        int DEVICESUMMARY = 2;
-
-        /**
-         * Access level for apps which can access usage for any app on the device, including apps
-         * running on other users/profiles.
-         *
-         * <p>Granted to:
-         * <ul>
-         * <li>Device owners.
-         * <li>Carrier-privileged applications.
-         * <li>The system UID.
-         * </ul>
-         */
-        int DEVICE = 3;
-    }
-
-    /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
-    public static @NetworkStatsAccess.Level int checkAccessLevel(
-            Context context, int callingPid, int callingUid, String callingPackage) {
-        final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class);
-        final TelephonyManager tm = (TelephonyManager)
-                context.getSystemService(Context.TELEPHONY_SERVICE);
-        boolean hasCarrierPrivileges;
-        final long token = Binder.clearCallingIdentity();
-        try {
-            hasCarrierPrivileges = tm != null
-                    && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
-                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage);
-        final int appId = UserHandle.getAppId(callingUid);
-
-        final boolean isNetworkStack = context.checkPermission(
-                android.Manifest.permission.NETWORK_STACK, callingPid, callingUid)
-                == PERMISSION_GRANTED;
-
-        if (hasCarrierPrivileges || isDeviceOwner
-                || appId == Process.SYSTEM_UID || isNetworkStack) {
-            // Carrier-privileged apps and device owners, and the system (including the
-            // network stack) can access data usage for all apps on the device.
-            return NetworkStatsAccess.Level.DEVICE;
-        }
-
-        boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
-        if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
-                READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
-            return NetworkStatsAccess.Level.DEVICESUMMARY;
-        }
-
-        //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
-        boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage)
-                || mDpm.isDeviceOwnerApp(callingPackage));
-        if (isProfileOwner) {
-            // Apps with the AppOps permission, profile owners, and apps with the privileged
-            // permission can access data usage for all apps in this user/profile.
-            return NetworkStatsAccess.Level.USER;
-        }
-
-        // Everyone else gets default access (only to their own UID).
-        return NetworkStatsAccess.Level.DEFAULT;
-    }
-
-    /**
-     * Returns whether the given caller should be able to access the given UID when the caller has
-     * the given {@link NetworkStatsAccess.Level}.
-     */
-    public static boolean isAccessibleToUser(int uid, int callerUid,
-            @NetworkStatsAccess.Level int accessLevel) {
-        final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
-        final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier();
-        switch (accessLevel) {
-            case NetworkStatsAccess.Level.DEVICE:
-                // Device-level access - can access usage for any uid.
-                return true;
-            case NetworkStatsAccess.Level.DEVICESUMMARY:
-                // Can access usage for any app running in the same user, along
-                // with some special uids (system, removed, or tethering) and
-                // anonymized uids
-                return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
-                        || uid == UID_TETHERING || uid == UID_ALL
-                        || userId == callerUserId;
-            case NetworkStatsAccess.Level.USER:
-                // User-level access - can access usage for any app running in the same user, along
-                // with some special uids (system, removed, or tethering).
-                return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
-                        || uid == UID_TETHERING
-                        || userId == callerUserId;
-            case NetworkStatsAccess.Level.DEFAULT:
-            default:
-                // Default access level - can only access one's own usage.
-                return uid == callerUid;
-        }
-    }
-
-    private static boolean hasAppOpsPermission(
-            Context context, int callingUid, String callingPackage) {
-        if (callingPackage != null) {
-            AppOpsManager appOps = (AppOpsManager) context.getSystemService(
-                    Context.APP_OPS_SERVICE);
-
-            final int mode = appOps.noteOp(AppOpsManager.OPSTR_GET_USAGE_STATS,
-                    callingUid, callingPackage, null /* attributionTag */, null /* message */);
-            if (mode == AppOpsManager.MODE_DEFAULT) {
-                // The default behavior here is to check if PackageManager has given the app
-                // permission.
-                final int permissionCheck = context.checkCallingPermission(
-                        Manifest.permission.PACKAGE_USAGE_STATS);
-                return permissionCheck == PackageManager.PERMISSION_GRANTED;
-            }
-            return (mode == AppOpsManager.MODE_ALLOWED);
-        }
-        return false;
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
deleted file mode 100644
index e385b33..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ /dev/null
@@ -1,956 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
-import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.ROAMING_YES;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.TrafficStats.UID_REMOVED;
-import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.net.NetworkStats.State;
-import android.net.NetworkStatsHistory.Entry;
-import android.os.Binder;
-import android.service.NetworkStatsCollectionKeyProto;
-import android.service.NetworkStatsCollectionProto;
-import android.service.NetworkStatsCollectionStatsProto;
-import android.telephony.SubscriptionPlan;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.AtomicFile;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-import android.util.Range;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FileRotator;
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.io.IoUtils;
-
-import java.io.BufferedInputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.ProtocolException;
-import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * Collection of {@link NetworkStatsHistory}, stored based on combined key of
- * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer {
-    private static final String TAG = NetworkStatsCollection.class.getSimpleName();
-    /** File header magic number: "ANET" */
-    private static final int FILE_MAGIC = 0x414E4554;
-
-    private static final int VERSION_NETWORK_INIT = 1;
-
-    private static final int VERSION_UID_INIT = 1;
-    private static final int VERSION_UID_WITH_IDENT = 2;
-    private static final int VERSION_UID_WITH_TAG = 3;
-    private static final int VERSION_UID_WITH_SET = 4;
-
-    private static final int VERSION_UNIFIED_INIT = 16;
-
-    private ArrayMap<Key, NetworkStatsHistory> mStats = new ArrayMap<>();
-
-    private final long mBucketDurationMillis;
-
-    private long mStartMillis;
-    private long mEndMillis;
-    private long mTotalBytes;
-    private boolean mDirty;
-
-    /**
-     * Construct a {@link NetworkStatsCollection} object.
-     *
-     * @param bucketDuration duration of the buckets in this object, in milliseconds.
-     * @hide
-     */
-    public NetworkStatsCollection(long bucketDurationMillis) {
-        mBucketDurationMillis = bucketDurationMillis;
-        reset();
-    }
-
-    /** @hide */
-    public void clear() {
-        reset();
-    }
-
-    /** @hide */
-    public void reset() {
-        mStats.clear();
-        mStartMillis = Long.MAX_VALUE;
-        mEndMillis = Long.MIN_VALUE;
-        mTotalBytes = 0;
-        mDirty = false;
-    }
-
-    /** @hide */
-    public long getStartMillis() {
-        return mStartMillis;
-    }
-
-    /**
-     * Return first atomic bucket in this collection, which is more conservative
-     * than {@link #mStartMillis}.
-     * @hide
-     */
-    public long getFirstAtomicBucketMillis() {
-        if (mStartMillis == Long.MAX_VALUE) {
-            return Long.MAX_VALUE;
-        } else {
-            return mStartMillis + mBucketDurationMillis;
-        }
-    }
-
-    /** @hide */
-    public long getEndMillis() {
-        return mEndMillis;
-    }
-
-    /** @hide */
-    public long getTotalBytes() {
-        return mTotalBytes;
-    }
-
-    /** @hide */
-    public boolean isDirty() {
-        return mDirty;
-    }
-
-    /** @hide */
-    public void clearDirty() {
-        mDirty = false;
-    }
-
-    /** @hide */
-    public boolean isEmpty() {
-        return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public long roundUp(long time) {
-        if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
-                || time == SubscriptionPlan.TIME_UNKNOWN) {
-            return time;
-        } else {
-            final long mod = time % mBucketDurationMillis;
-            if (mod > 0) {
-                time -= mod;
-                time += mBucketDurationMillis;
-            }
-            return time;
-        }
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public long roundDown(long time) {
-        if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
-                || time == SubscriptionPlan.TIME_UNKNOWN) {
-            return time;
-        } else {
-            final long mod = time % mBucketDurationMillis;
-            if (mod > 0) {
-                time -= mod;
-            }
-            return time;
-        }
-    }
-
-    /** @hide */
-    public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
-        return getRelevantUids(accessLevel, Binder.getCallingUid());
-    }
-
-    /** @hide */
-    public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
-                final int callerUid) {
-        final ArrayList<Integer> uids = new ArrayList<>();
-        for (int i = 0; i < mStats.size(); i++) {
-            final Key key = mStats.keyAt(i);
-            if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) {
-                int j = Collections.binarySearch(uids, new Integer(key.uid));
-
-                if (j < 0) {
-                    j = ~j;
-                    uids.add(j, key.uid);
-                }
-            }
-        }
-        return CollectionUtils.toIntArray(uids);
-    }
-
-    /**
-     * Combine all {@link NetworkStatsHistory} in this collection which match
-     * the requested parameters.
-     * @hide
-     */
-    public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan,
-            int uid, int set, int tag, int fields, long start, long end,
-            @NetworkStatsAccess.Level int accessLevel, int callerUid) {
-        if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) {
-            throw new SecurityException("Network stats history of uid " + uid
-                    + " is forbidden for caller " + callerUid);
-        }
-
-        // 180 days of history should be enough for anyone; if we end up needing
-        // more, we'll dynamically grow the history object.
-        final int bucketEstimate = (int) NetworkStatsUtils.constrain(
-                ((end - start) / mBucketDurationMillis), 0,
-                (180 * DateUtils.DAY_IN_MILLIS) / mBucketDurationMillis);
-        final NetworkStatsHistory combined = new NetworkStatsHistory(
-                mBucketDurationMillis, bucketEstimate, fields);
-
-        // shortcut when we know stats will be empty
-        if (start == end) return combined;
-
-        // Figure out the window of time that we should be augmenting (if any)
-        long augmentStart = SubscriptionPlan.TIME_UNKNOWN;
-        long augmentEnd = (augmentPlan != null) ? augmentPlan.getDataUsageTime()
-                : SubscriptionPlan.TIME_UNKNOWN;
-        // And if augmenting, we might need to collect more data to adjust with
-        long collectStart = start;
-        long collectEnd = end;
-
-        if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) {
-            final Iterator<Range<ZonedDateTime>> it = augmentPlan.cycleIterator();
-            while (it.hasNext()) {
-                final Range<ZonedDateTime> cycle = it.next();
-                final long cycleStart = cycle.getLower().toInstant().toEpochMilli();
-                final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli();
-                if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) {
-                    augmentStart = cycleStart;
-                    collectStart = Long.min(collectStart, augmentStart);
-                    collectEnd = Long.max(collectEnd, augmentEnd);
-                    break;
-                }
-            }
-        }
-
-        if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) {
-            // Shrink augmentation window so we don't risk undercounting.
-            augmentStart = roundUp(augmentStart);
-            augmentEnd = roundDown(augmentEnd);
-            // Grow collection window so we get all the stats needed.
-            collectStart = roundDown(collectStart);
-            collectEnd = roundUp(collectEnd);
-        }
-
-        for (int i = 0; i < mStats.size(); i++) {
-            final Key key = mStats.keyAt(i);
-            if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag
-                    && templateMatches(template, key.ident)) {
-                final NetworkStatsHistory value = mStats.valueAt(i);
-                combined.recordHistory(value, collectStart, collectEnd);
-            }
-        }
-
-        if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) {
-            final NetworkStatsHistory.Entry entry = combined.getValues(
-                    augmentStart, augmentEnd, null);
-
-            // If we don't have any recorded data for this time period, give
-            // ourselves something to scale with.
-            if (entry.rxBytes == 0 || entry.txBytes == 0) {
-                combined.recordData(augmentStart, augmentEnd,
-                        new NetworkStats.Entry(1, 0, 1, 0, 0));
-                combined.getValues(augmentStart, augmentEnd, entry);
-            }
-
-            final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 :
-                    (entry.rxBytes + entry.txBytes);
-            final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
-            final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
-            final long targetBytes = augmentPlan.getDataUsageBytes();
-
-            final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes);
-            final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes);
-
-
-            // Scale all matching buckets to reach anchor target
-            final long beforeTotal = combined.getTotalBytes();
-            for (int i = 0; i < combined.size(); i++) {
-                combined.getValues(i, entry);
-                if (entry.bucketStart >= augmentStart
-                        && entry.bucketStart + entry.bucketDuration <= augmentEnd) {
-                    entry.rxBytes = multiplySafeByRational(
-                            targetRxBytes, entry.rxBytes, rawRxBytes);
-                    entry.txBytes = multiplySafeByRational(
-                            targetTxBytes, entry.txBytes, rawTxBytes);
-                    // We purposefully clear out packet counters to indicate
-                    // that this data has been augmented.
-                    entry.rxPackets = 0;
-                    entry.txPackets = 0;
-                    combined.setValues(i, entry);
-                }
-            }
-
-            final long deltaTotal = combined.getTotalBytes() - beforeTotal;
-            if (deltaTotal != 0) {
-                Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes");
-            }
-
-            // Finally we can slice data as originally requested
-            final NetworkStatsHistory sliced = new NetworkStatsHistory(
-                    mBucketDurationMillis, bucketEstimate, fields);
-            sliced.recordHistory(combined, start, end);
-            return sliced;
-        } else {
-            return combined;
-        }
-    }
-
-    /**
-     * Summarize all {@link NetworkStatsHistory} in this collection which match
-     * the requested parameters across the requested range.
-     *
-     * @param template - a predicate for filtering netstats.
-     * @param start - start of the range, timestamp in milliseconds since the epoch.
-     * @param end - end of the range, timestamp in milliseconds since the epoch.
-     * @param accessLevel - caller access level.
-     * @param callerUid - caller UID.
-     * @hide
-     */
-    public NetworkStats getSummary(NetworkTemplate template, long start, long end,
-            @NetworkStatsAccess.Level int accessLevel, int callerUid) {
-        final long now = System.currentTimeMillis();
-
-        final NetworkStats stats = new NetworkStats(end - start, 24);
-
-        // shortcut when we know stats will be empty
-        if (start == end) return stats;
-
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-        NetworkStatsHistory.Entry historyEntry = null;
-
-        for (int i = 0; i < mStats.size(); i++) {
-            final Key key = mStats.keyAt(i);
-            if (templateMatches(template, key.ident)
-                    && NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)
-                    && key.set < NetworkStats.SET_DEBUG_START) {
-                final NetworkStatsHistory value = mStats.valueAt(i);
-                historyEntry = value.getValues(start, end, now, historyEntry);
-
-                entry.iface = IFACE_ALL;
-                entry.uid = key.uid;
-                entry.set = key.set;
-                entry.tag = key.tag;
-                entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork()
-                        ? DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO;
-                entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO;
-                entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO;
-                entry.rxBytes = historyEntry.rxBytes;
-                entry.rxPackets = historyEntry.rxPackets;
-                entry.txBytes = historyEntry.txBytes;
-                entry.txPackets = historyEntry.txPackets;
-                entry.operations = historyEntry.operations;
-
-                if (!entry.isEmpty()) {
-                    stats.combineValues(entry);
-                }
-            }
-        }
-
-        return stats;
-    }
-
-    /**
-     * Record given {@link android.net.NetworkStats.Entry} into this collection.
-     * @hide
-     */
-    public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
-            long end, NetworkStats.Entry entry) {
-        final NetworkStatsHistory history = findOrCreateHistory(ident, uid, set, tag);
-        history.recordData(start, end, entry);
-        noteRecordedHistory(history.getStart(), history.getEnd(), entry.rxBytes + entry.txBytes);
-    }
-
-    /**
-     * Record given {@link NetworkStatsHistory} into this collection.
-     *
-     * @hide
-     */
-    public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) {
-        Objects.requireNonNull(key);
-        Objects.requireNonNull(history);
-        if (history.size() == 0) return;
-        noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
-
-        NetworkStatsHistory target = mStats.get(key);
-        if (target == null) {
-            target = new NetworkStatsHistory(history.getBucketDuration());
-            mStats.put(key, target);
-        }
-        target.recordEntireHistory(history);
-    }
-
-    /**
-     * Record all {@link NetworkStatsHistory} contained in the given collection
-     * into this collection.
-     *
-     * @hide
-     */
-    public void recordCollection(@NonNull NetworkStatsCollection another) {
-        Objects.requireNonNull(another);
-        for (int i = 0; i < another.mStats.size(); i++) {
-            final Key key = another.mStats.keyAt(i);
-            final NetworkStatsHistory value = another.mStats.valueAt(i);
-            recordHistory(key, value);
-        }
-    }
-
-    private NetworkStatsHistory findOrCreateHistory(
-            NetworkIdentitySet ident, int uid, int set, int tag) {
-        final Key key = new Key(ident, uid, set, tag);
-        final NetworkStatsHistory existing = mStats.get(key);
-
-        // update when no existing, or when bucket duration changed
-        NetworkStatsHistory updated = null;
-        if (existing == null) {
-            updated = new NetworkStatsHistory(mBucketDurationMillis, 10);
-        } else if (existing.getBucketDuration() != mBucketDurationMillis) {
-            updated = new NetworkStatsHistory(existing, mBucketDurationMillis);
-        }
-
-        if (updated != null) {
-            mStats.put(key, updated);
-            return updated;
-        } else {
-            return existing;
-        }
-    }
-
-    /** @hide */
-    @Override
-    public void read(InputStream in) throws IOException {
-        read((DataInput) new DataInputStream(in));
-    }
-
-    private void read(DataInput in) throws IOException {
-        // verify file magic header intact
-        final int magic = in.readInt();
-        if (magic != FILE_MAGIC) {
-            throw new ProtocolException("unexpected magic: " + magic);
-        }
-
-        final int version = in.readInt();
-        switch (version) {
-            case VERSION_UNIFIED_INIT: {
-                // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
-                final int identSize = in.readInt();
-                for (int i = 0; i < identSize; i++) {
-                    final NetworkIdentitySet ident = new NetworkIdentitySet(in);
-
-                    final int size = in.readInt();
-                    for (int j = 0; j < size; j++) {
-                        final int uid = in.readInt();
-                        final int set = in.readInt();
-                        final int tag = in.readInt();
-
-                        final Key key = new Key(ident, uid, set, tag);
-                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
-                        recordHistory(key, history);
-                    }
-                }
-                break;
-            }
-            default: {
-                throw new ProtocolException("unexpected version: " + version);
-            }
-        }
-    }
-
-    /** @hide */
-    @Override
-    public void write(OutputStream out) throws IOException {
-        write((DataOutput) new DataOutputStream(out));
-        out.flush();
-    }
-
-    private void write(DataOutput out) throws IOException {
-        // cluster key lists grouped by ident
-        final HashMap<NetworkIdentitySet, ArrayList<Key>> keysByIdent = new HashMap<>();
-        for (Key key : mStats.keySet()) {
-            ArrayList<Key> keys = keysByIdent.get(key.ident);
-            if (keys == null) {
-                keys = new ArrayList<>();
-                keysByIdent.put(key.ident, keys);
-            }
-            keys.add(key);
-        }
-
-        out.writeInt(FILE_MAGIC);
-        out.writeInt(VERSION_UNIFIED_INIT);
-
-        out.writeInt(keysByIdent.size());
-        for (NetworkIdentitySet ident : keysByIdent.keySet()) {
-            final ArrayList<Key> keys = keysByIdent.get(ident);
-            ident.writeToStream(out);
-
-            out.writeInt(keys.size());
-            for (Key key : keys) {
-                final NetworkStatsHistory history = mStats.get(key);
-                out.writeInt(key.uid);
-                out.writeInt(key.set);
-                out.writeInt(key.tag);
-                history.writeToStream(out);
-            }
-        }
-    }
-
-    /**
-     * Read legacy network summary statistics file format into the collection,
-     * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
-     *
-     * @deprecated
-     * @hide
-     */
-    @Deprecated
-    public void readLegacyNetwork(File file) throws IOException {
-        final AtomicFile inputFile = new AtomicFile(file);
-
-        DataInputStream in = null;
-        try {
-            in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
-
-            // verify file magic header intact
-            final int magic = in.readInt();
-            if (magic != FILE_MAGIC) {
-                throw new ProtocolException("unexpected magic: " + magic);
-            }
-
-            final int version = in.readInt();
-            switch (version) {
-                case VERSION_NETWORK_INIT: {
-                    // network := size *(NetworkIdentitySet NetworkStatsHistory)
-                    final int size = in.readInt();
-                    for (int i = 0; i < size; i++) {
-                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
-                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
-                        final Key key = new Key(ident, UID_ALL, SET_ALL, TAG_NONE);
-                        recordHistory(key, history);
-                    }
-                    break;
-                }
-                default: {
-                    throw new ProtocolException("unexpected version: " + version);
-                }
-            }
-        } catch (FileNotFoundException e) {
-            // missing stats is okay, probably first boot
-        } finally {
-            IoUtils.closeQuietly(in);
-        }
-    }
-
-    /**
-     * Read legacy Uid statistics file format into the collection,
-     * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
-     *
-     * @deprecated
-     * @hide
-     */
-    @Deprecated
-    public void readLegacyUid(File file, boolean onlyTags) throws IOException {
-        final AtomicFile inputFile = new AtomicFile(file);
-
-        DataInputStream in = null;
-        try {
-            in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
-
-            // verify file magic header intact
-            final int magic = in.readInt();
-            if (magic != FILE_MAGIC) {
-                throw new ProtocolException("unexpected magic: " + magic);
-            }
-
-            final int version = in.readInt();
-            switch (version) {
-                case VERSION_UID_INIT: {
-                    // uid := size *(UID NetworkStatsHistory)
-
-                    // drop this data version, since we don't have a good
-                    // mapping into NetworkIdentitySet.
-                    break;
-                }
-                case VERSION_UID_WITH_IDENT: {
-                    // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
-
-                    // drop this data version, since this version only existed
-                    // for a short time.
-                    break;
-                }
-                case VERSION_UID_WITH_TAG:
-                case VERSION_UID_WITH_SET: {
-                    // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
-                    final int identSize = in.readInt();
-                    for (int i = 0; i < identSize; i++) {
-                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
-
-                        final int size = in.readInt();
-                        for (int j = 0; j < size; j++) {
-                            final int uid = in.readInt();
-                            final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
-                                    : SET_DEFAULT;
-                            final int tag = in.readInt();
-
-                            final Key key = new Key(ident, uid, set, tag);
-                            final NetworkStatsHistory history = new NetworkStatsHistory(in);
-
-                            if ((tag == TAG_NONE) != onlyTags) {
-                                recordHistory(key, history);
-                            }
-                        }
-                    }
-                    break;
-                }
-                default: {
-                    throw new ProtocolException("unexpected version: " + version);
-                }
-            }
-        } catch (FileNotFoundException e) {
-            // missing stats is okay, probably first boot
-        } finally {
-            IoUtils.closeQuietly(in);
-        }
-    }
-
-    /**
-     * Remove any {@link NetworkStatsHistory} attributed to the requested UID,
-     * moving any {@link NetworkStats#TAG_NONE} series to
-     * {@link TrafficStats#UID_REMOVED}.
-     * @hide
-     */
-    public void removeUids(int[] uids) {
-        final ArrayList<Key> knownKeys = new ArrayList<>();
-        knownKeys.addAll(mStats.keySet());
-
-        // migrate all UID stats into special "removed" bucket
-        for (Key key : knownKeys) {
-            if (CollectionUtils.contains(uids, key.uid)) {
-                // only migrate combined TAG_NONE history
-                if (key.tag == TAG_NONE) {
-                    final NetworkStatsHistory uidHistory = mStats.get(key);
-                    final NetworkStatsHistory removedHistory = findOrCreateHistory(
-                            key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
-                    removedHistory.recordEntireHistory(uidHistory);
-                }
-                mStats.remove(key);
-                mDirty = true;
-            }
-        }
-    }
-
-    private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) {
-        if (startMillis < mStartMillis) mStartMillis = startMillis;
-        if (endMillis > mEndMillis) mEndMillis = endMillis;
-        mTotalBytes += totalBytes;
-        mDirty = true;
-    }
-
-    private int estimateBuckets() {
-        return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5)
-                / mBucketDurationMillis);
-    }
-
-    private ArrayList<Key> getSortedKeys() {
-        final ArrayList<Key> keys = new ArrayList<>();
-        keys.addAll(mStats.keySet());
-        Collections.sort(keys, (left, right) -> Key.compare(left, right));
-        return keys;
-    }
-
-    /** @hide */
-    public void dump(IndentingPrintWriter pw) {
-        for (Key key : getSortedKeys()) {
-            pw.print("ident="); pw.print(key.ident.toString());
-            pw.print(" uid="); pw.print(key.uid);
-            pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
-            pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
-
-            final NetworkStatsHistory history = mStats.get(key);
-            pw.increaseIndent();
-            history.dump(pw, true);
-            pw.decreaseIndent();
-        }
-    }
-
-    /** @hide */
-    public void dumpDebug(ProtoOutputStream proto, long tag) {
-        final long start = proto.start(tag);
-
-        for (Key key : getSortedKeys()) {
-            final long startStats = proto.start(NetworkStatsCollectionProto.STATS);
-
-            // Key
-            final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY);
-            key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY);
-            proto.write(NetworkStatsCollectionKeyProto.UID, key.uid);
-            proto.write(NetworkStatsCollectionKeyProto.SET, key.set);
-            proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag);
-            proto.end(startKey);
-
-            // Value
-            final NetworkStatsHistory history = mStats.get(key);
-            history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY);
-            proto.end(startStats);
-        }
-
-        proto.end(start);
-    }
-
-    /** @hide */
-    public void dumpCheckin(PrintWriter pw, long start, long end) {
-        dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
-        dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
-        dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateEthernet(), "eth");
-        dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateBluetooth(), "bt");
-    }
-
-    /**
-     * Dump all contained stats that match requested parameters, but group
-     * together all matching {@link NetworkTemplate} under a single prefix.
-     */
-    private void dumpCheckin(PrintWriter pw, long start, long end, NetworkTemplate groupTemplate,
-            String groupPrefix) {
-        final ArrayMap<Key, NetworkStatsHistory> grouped = new ArrayMap<>();
-
-        // Walk through all history, grouping by matching network templates
-        for (int i = 0; i < mStats.size(); i++) {
-            final Key key = mStats.keyAt(i);
-            final NetworkStatsHistory value = mStats.valueAt(i);
-
-            if (!templateMatches(groupTemplate, key.ident)) continue;
-            if (key.set >= NetworkStats.SET_DEBUG_START) continue;
-
-            final Key groupKey = new Key(null, key.uid, key.set, key.tag);
-            NetworkStatsHistory groupHistory = grouped.get(groupKey);
-            if (groupHistory == null) {
-                groupHistory = new NetworkStatsHistory(value.getBucketDuration());
-                grouped.put(groupKey, groupHistory);
-            }
-            groupHistory.recordHistory(value, start, end);
-        }
-
-        for (int i = 0; i < grouped.size(); i++) {
-            final Key key = grouped.keyAt(i);
-            final NetworkStatsHistory value = grouped.valueAt(i);
-
-            if (value.size() == 0) continue;
-
-            pw.print("c,");
-            pw.print(groupPrefix); pw.print(',');
-            pw.print(key.uid); pw.print(',');
-            pw.print(NetworkStats.setToCheckinString(key.set)); pw.print(',');
-            pw.print(key.tag);
-            pw.println();
-
-            value.dumpCheckin(pw);
-        }
-    }
-
-    /**
-     * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
-     * in the given {@link NetworkIdentitySet}.
-     */
-    private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
-        for (NetworkIdentity ident : identSet) {
-            if (template.matches(ident)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Get the all historical stats of the collection {@link NetworkStatsCollection}.
-     *
-     * @return All {@link NetworkStatsHistory} in this collection.
-     */
-    @NonNull
-    public Map<Key, NetworkStatsHistory> getEntries() {
-        return new ArrayMap(mStats);
-    }
-
-    /**
-     * Builder class for {@link NetworkStatsCollection}.
-     */
-    public static final class Builder {
-        private final long mBucketDurationMillis;
-        private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>();
-
-        /**
-         * Creates a new Builder with given bucket duration.
-         *
-         * @param bucketDuration Duration of the buckets of the object, in milliseconds.
-         */
-        public Builder(long bucketDurationMillis) {
-            mBucketDurationMillis = bucketDurationMillis;
-        }
-
-        /**
-         * Add association of the history with the specified key in this map.
-         *
-         * @param key The object used to identify a network, see {@link Key}.
-         * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}.
-         * @return The builder object.
-         */
-        @NonNull
-        public NetworkStatsCollection.Builder addEntry(@NonNull Key key,
-                @NonNull NetworkStatsHistory history) {
-            Objects.requireNonNull(key);
-            Objects.requireNonNull(history);
-            final List<Entry> historyEntries = history.getEntries();
-
-            final NetworkStatsHistory.Builder historyBuilder =
-                    new NetworkStatsHistory.Builder(mBucketDurationMillis, historyEntries.size());
-            for (Entry entry : historyEntries) {
-                historyBuilder.addEntry(entry);
-            }
-
-            mEntries.put(key, historyBuilder.build());
-            return this;
-        }
-
-        /**
-         * Builds the instance of the {@link NetworkStatsCollection}.
-         *
-         * @return the built instance of {@link NetworkStatsCollection}.
-         */
-        @NonNull
-        public NetworkStatsCollection build() {
-            final NetworkStatsCollection collection =
-                    new NetworkStatsCollection(mBucketDurationMillis);
-            for (int i = 0; i < mEntries.size(); i++) {
-                collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i));
-            }
-            return collection;
-        }
-    }
-
-    /**
-     * the identifier that associate with the {@link NetworkStatsHistory} object to identify
-     * a certain record in the {@link NetworkStatsCollection} object.
-     */
-    public static final class Key {
-        /** @hide */
-        public final NetworkIdentitySet ident;
-        /** @hide */
-        public final int uid;
-        /** @hide */
-        public final int set;
-        /** @hide */
-        public final int tag;
-
-        private final int mHashCode;
-
-        /**
-         * Construct a {@link Key} object.
-         *
-         * @param ident a Set of {@link NetworkIdentity} that associated with the record.
-         * @param uid Uid of the record.
-         * @param set Set of the record, see {@code NetworkStats#SET_*}.
-         * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}.
-         */
-        public Key(@NonNull Set<NetworkIdentity> ident, int uid, @State int set, int tag) {
-            this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag);
-        }
-
-        /** @hide */
-        public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) {
-            this.ident = Objects.requireNonNull(ident);
-            this.uid = uid;
-            this.set = set;
-            this.tag = tag;
-            mHashCode = Objects.hash(ident, uid, set, tag);
-        }
-
-        @Override
-        public int hashCode() {
-            return mHashCode;
-        }
-
-        @Override
-        public boolean equals(@Nullable Object obj) {
-            if (obj instanceof Key) {
-                final Key key = (Key) obj;
-                return uid == key.uid && set == key.set && tag == key.tag
-                        && Objects.equals(ident, key.ident);
-            }
-            return false;
-        }
-
-        /** @hide */
-        public static int compare(@NonNull Key left, @NonNull Key right) {
-            Objects.requireNonNull(left);
-            Objects.requireNonNull(right);
-            int res = 0;
-            if (left.ident != null && right.ident != null) {
-                res = NetworkIdentitySet.compare(left.ident, right.ident);
-            }
-            if (res == 0) {
-                res = Integer.compare(left.uid, right.uid);
-            }
-            if (res == 0) {
-                res = Integer.compare(left.set, right.set);
-            }
-            if (res == 0) {
-                res = Integer.compare(left.tag, right.tag);
-            }
-            return res;
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl
deleted file mode 100644
index 8b9069f..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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;
-
-parcelable NetworkStatsHistory;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
deleted file mode 100644
index 301fef9..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray;
-import static android.net.NetworkStatsHistory.DataStreamUtils.readVarLongArray;
-import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray;
-import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
-import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
-import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.service.NetworkStatsHistoryBucketProto;
-import android.service.NetworkStatsHistoryProto;
-import android.util.IndentingPrintWriter;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.util.EmptyArray;
-
-import java.io.CharArrayWriter;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.ProtocolException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
-/**
- * Collection of historical network statistics, recorded into equally-sized
- * "buckets" in time. Internally it stores data in {@code long} series for more
- * efficient persistence.
- * <p>
- * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for
- * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is
- * sorted at all times.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class NetworkStatsHistory implements Parcelable {
-    private static final int VERSION_INIT = 1;
-    private static final int VERSION_ADD_PACKETS = 2;
-    private static final int VERSION_ADD_ACTIVE = 3;
-
-    /** @hide */
-    public static final int FIELD_ACTIVE_TIME = 0x01;
-    /** @hide */
-    public static final int FIELD_RX_BYTES = 0x02;
-    /** @hide */
-    public static final int FIELD_RX_PACKETS = 0x04;
-    /** @hide */
-    public static final int FIELD_TX_BYTES = 0x08;
-    /** @hide */
-    public static final int FIELD_TX_PACKETS = 0x10;
-    /** @hide */
-    public static final int FIELD_OPERATIONS = 0x20;
-    /** @hide */
-    public static final int FIELD_ALL = 0xFFFFFFFF;
-
-    private long bucketDuration;
-    private int bucketCount;
-    private long[] bucketStart;
-    private long[] activeTime;
-    private long[] rxBytes;
-    private long[] rxPackets;
-    private long[] txBytes;
-    private long[] txPackets;
-    private long[] operations;
-    private long totalBytes;
-
-    /** @hide */
-    public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime,
-            long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets,
-            long[] operations, int bucketCount, long totalBytes) {
-        this.bucketDuration = bucketDuration;
-        this.bucketStart = bucketStart;
-        this.activeTime = activeTime;
-        this.rxBytes = rxBytes;
-        this.rxPackets = rxPackets;
-        this.txBytes = txBytes;
-        this.txPackets = txPackets;
-        this.operations = operations;
-        this.bucketCount = bucketCount;
-        this.totalBytes = totalBytes;
-    }
-
-    /**
-     * An instance to represent a single record in a {@link NetworkStatsHistory} object.
-     */
-    public static final class Entry {
-        /** @hide */
-        public static final long UNKNOWN = -1;
-
-        /** @hide */
-        // TODO: Migrate all callers to get duration from the history object and remove this field.
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long bucketDuration;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long bucketStart;
-        /** @hide */
-        public long activeTime;
-        /** @hide */
-        @UnsupportedAppUsage
-        public long rxBytes;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long rxPackets;
-        /** @hide */
-        @UnsupportedAppUsage
-        public long txBytes;
-        /** @hide */
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-        public long txPackets;
-        /** @hide */
-        public long operations;
-        /** @hide */
-        Entry() {}
-
-        /**
-         * Construct a {@link Entry} instance to represent a single record in a
-         * {@link NetworkStatsHistory} object.
-         *
-         * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the
-         *                    Unix epoch, see {@link java.lang.System#currentTimeMillis}.
-         * @param activeTime Active time for this {@link Entry}, in milliseconds.
-         * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
-         *                represent the contents of IP packets, including IP headers.
-         * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
-         *                  represent the contents of IP packets, including IP headers.
-         * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
-         *                represent the contents of IP packets, including IP headers.
-         * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
-         *                  represent the contents of IP packets, including IP headers.
-         * @param operations count of network operations performed for this {@link Entry}. This can
-         *                   be used to derive bytes-per-operation.
-         */
-        public Entry(long bucketStart, long activeTime, long rxBytes,
-                long rxPackets, long txBytes, long txPackets, long operations) {
-            this.bucketStart = bucketStart;
-            this.activeTime = activeTime;
-            this.rxBytes = rxBytes;
-            this.rxPackets = rxPackets;
-            this.txBytes = txBytes;
-            this.txPackets = txPackets;
-            this.operations = operations;
-        }
-
-        /**
-         * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch.
-         */
-        public long getBucketStart() {
-            return bucketStart;
-        }
-
-        /**
-         * Get active time of the bucket's time interval, in milliseconds.
-         */
-        public long getActiveTime() {
-            return activeTime;
-        }
-
-        /** Get number of bytes received for this {@link Entry}. */
-        public long getRxBytes() {
-            return rxBytes;
-        }
-
-        /** Get number of packets received for this {@link Entry}. */
-        public long getRxPackets() {
-            return rxPackets;
-        }
-
-        /** Get number of bytes transmitted for this {@link Entry}. */
-        public long getTxBytes() {
-            return txBytes;
-        }
-
-        /** Get number of packets transmitted for this {@link Entry}. */
-        public long getTxPackets() {
-            return txPackets;
-        }
-
-        /** Get count of network operations performed for this {@link Entry}. */
-        public long getOperations() {
-            return operations;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o.getClass() != getClass()) return false;
-            Entry entry = (Entry) o;
-            return bucketStart == entry.bucketStart
-                    && activeTime == entry.activeTime && rxBytes == entry.rxBytes
-                    && rxPackets == entry.rxPackets && txBytes == entry.txBytes
-                    && txPackets == entry.txPackets && operations == entry.operations;
-        }
-
-        @Override
-        public int hashCode() {
-            return (int) (bucketStart * 2
-                    + activeTime * 3
-                    + rxBytes * 5
-                    + rxPackets * 7
-                    + txBytes * 11
-                    + txPackets * 13
-                    + operations * 17);
-        }
-
-        @Override
-        public String toString() {
-            return "Entry{"
-                    + "bucketStart=" + bucketStart
-                    + ", activeTime=" + activeTime
-                    + ", rxBytes=" + rxBytes
-                    + ", rxPackets=" + rxPackets
-                    + ", txBytes=" + txBytes
-                    + ", txPackets=" + txPackets
-                    + ", operations=" + operations
-                    + "}";
-        }
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public NetworkStatsHistory(long bucketDuration) {
-        this(bucketDuration, 10, FIELD_ALL);
-    }
-
-    /** @hide */
-    public NetworkStatsHistory(long bucketDuration, int initialSize) {
-        this(bucketDuration, initialSize, FIELD_ALL);
-    }
-
-    /** @hide */
-    public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
-        this.bucketDuration = bucketDuration;
-        bucketStart = new long[initialSize];
-        if ((fields & FIELD_ACTIVE_TIME) != 0) activeTime = new long[initialSize];
-        if ((fields & FIELD_RX_BYTES) != 0) rxBytes = new long[initialSize];
-        if ((fields & FIELD_RX_PACKETS) != 0) rxPackets = new long[initialSize];
-        if ((fields & FIELD_TX_BYTES) != 0) txBytes = new long[initialSize];
-        if ((fields & FIELD_TX_PACKETS) != 0) txPackets = new long[initialSize];
-        if ((fields & FIELD_OPERATIONS) != 0) operations = new long[initialSize];
-        bucketCount = 0;
-        totalBytes = 0;
-    }
-
-    /** @hide */
-    public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) {
-        this(bucketDuration, existing.estimateResizeBuckets(bucketDuration));
-        recordEntireHistory(existing);
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public NetworkStatsHistory(Parcel in) {
-        bucketDuration = in.readLong();
-        bucketStart = readLongArray(in);
-        activeTime = readLongArray(in);
-        rxBytes = readLongArray(in);
-        rxPackets = readLongArray(in);
-        txBytes = readLongArray(in);
-        txPackets = readLongArray(in);
-        operations = readLongArray(in);
-        bucketCount = bucketStart.length;
-        totalBytes = in.readLong();
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel out, int flags) {
-        out.writeLong(bucketDuration);
-        writeLongArray(out, bucketStart, bucketCount);
-        writeLongArray(out, activeTime, bucketCount);
-        writeLongArray(out, rxBytes, bucketCount);
-        writeLongArray(out, rxPackets, bucketCount);
-        writeLongArray(out, txBytes, bucketCount);
-        writeLongArray(out, txPackets, bucketCount);
-        writeLongArray(out, operations, bucketCount);
-        out.writeLong(totalBytes);
-    }
-
-    /** @hide */
-    public NetworkStatsHistory(DataInput in) throws IOException {
-        final int version = in.readInt();
-        switch (version) {
-            case VERSION_INIT: {
-                bucketDuration = in.readLong();
-                bucketStart = readFullLongArray(in);
-                rxBytes = readFullLongArray(in);
-                rxPackets = new long[bucketStart.length];
-                txBytes = readFullLongArray(in);
-                txPackets = new long[bucketStart.length];
-                operations = new long[bucketStart.length];
-                bucketCount = bucketStart.length;
-                totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
-                break;
-            }
-            case VERSION_ADD_PACKETS:
-            case VERSION_ADD_ACTIVE: {
-                bucketDuration = in.readLong();
-                bucketStart = readVarLongArray(in);
-                activeTime = (version >= VERSION_ADD_ACTIVE) ? readVarLongArray(in)
-                        : new long[bucketStart.length];
-                rxBytes = readVarLongArray(in);
-                rxPackets = readVarLongArray(in);
-                txBytes = readVarLongArray(in);
-                txPackets = readVarLongArray(in);
-                operations = readVarLongArray(in);
-                bucketCount = bucketStart.length;
-                totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes);
-                break;
-            }
-            default: {
-                throw new ProtocolException("unexpected version: " + version);
-            }
-        }
-
-        if (bucketStart.length != bucketCount || rxBytes.length != bucketCount
-                || rxPackets.length != bucketCount || txBytes.length != bucketCount
-                || txPackets.length != bucketCount || operations.length != bucketCount) {
-            throw new ProtocolException("Mismatched history lengths");
-        }
-    }
-
-    /** @hide */
-    public void writeToStream(DataOutput out) throws IOException {
-        out.writeInt(VERSION_ADD_ACTIVE);
-        out.writeLong(bucketDuration);
-        writeVarLongArray(out, bucketStart, bucketCount);
-        writeVarLongArray(out, activeTime, bucketCount);
-        writeVarLongArray(out, rxBytes, bucketCount);
-        writeVarLongArray(out, rxPackets, bucketCount);
-        writeVarLongArray(out, txBytes, bucketCount);
-        writeVarLongArray(out, txPackets, bucketCount);
-        writeVarLongArray(out, operations, bucketCount);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int size() {
-        return bucketCount;
-    }
-
-    /** @hide */
-    public long getBucketDuration() {
-        return bucketDuration;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public long getStart() {
-        if (bucketCount > 0) {
-            return bucketStart[0];
-        } else {
-            return Long.MAX_VALUE;
-        }
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public long getEnd() {
-        if (bucketCount > 0) {
-            return bucketStart[bucketCount - 1] + bucketDuration;
-        } else {
-            return Long.MIN_VALUE;
-        }
-    }
-
-    /**
-     * Return total bytes represented by this history.
-     * @hide
-     */
-    public long getTotalBytes() {
-        return totalBytes;
-    }
-
-    /**
-     * Return index of bucket that contains or is immediately before the
-     * requested time.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public int getIndexBefore(long time) {
-        int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
-        if (index < 0) {
-            index = (~index) - 1;
-        } else {
-            index -= 1;
-        }
-        return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
-    }
-
-    /**
-     * Return index of bucket that contains or is immediately after the
-     * requested time.
-     * @hide
-     */
-    public int getIndexAfter(long time) {
-        int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
-        if (index < 0) {
-            index = ~index;
-        } else {
-            index += 1;
-        }
-        return NetworkStatsUtils.constrain(index, 0, bucketCount - 1);
-    }
-
-    /**
-     * Return specific stats entry.
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public Entry getValues(int i, Entry recycle) {
-        final Entry entry = recycle != null ? recycle : new Entry();
-        entry.bucketStart = bucketStart[i];
-        entry.bucketDuration = bucketDuration;
-        entry.activeTime = getLong(activeTime, i, UNKNOWN);
-        entry.rxBytes = getLong(rxBytes, i, UNKNOWN);
-        entry.rxPackets = getLong(rxPackets, i, UNKNOWN);
-        entry.txBytes = getLong(txBytes, i, UNKNOWN);
-        entry.txPackets = getLong(txPackets, i, UNKNOWN);
-        entry.operations = getLong(operations, i, UNKNOWN);
-        return entry;
-    }
-
-    /**
-     * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance.
-     *
-     * @return
-     */
-    @NonNull
-    public List<Entry> getEntries() {
-        // TODO: Return a wrapper that uses this list instead, to prevent the returned result
-        //  from being changed.
-        final ArrayList<Entry> ret = new ArrayList<>(size());
-        for (int i = 0; i < size(); i++) {
-            ret.add(getValues(i, null /* recycle */));
-        }
-        return ret;
-    }
-
-    /** @hide */
-    public void setValues(int i, Entry entry) {
-        // Unwind old values
-        if (rxBytes != null) totalBytes -= rxBytes[i];
-        if (txBytes != null) totalBytes -= txBytes[i];
-
-        bucketStart[i] = entry.bucketStart;
-        setLong(activeTime, i, entry.activeTime);
-        setLong(rxBytes, i, entry.rxBytes);
-        setLong(rxPackets, i, entry.rxPackets);
-        setLong(txBytes, i, entry.txBytes);
-        setLong(txPackets, i, entry.txPackets);
-        setLong(operations, i, entry.operations);
-
-        // Apply new values
-        if (rxBytes != null) totalBytes += rxBytes[i];
-        if (txBytes != null) totalBytes += txBytes[i];
-    }
-
-    /**
-     * Record that data traffic occurred in the given time range. Will
-     * distribute across internal buckets, creating new buckets as needed.
-     * @hide
-     */
-    @Deprecated
-    public void recordData(long start, long end, long rxBytes, long txBytes) {
-        recordData(start, end, new NetworkStats.Entry(
-                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
-    }
-
-    /**
-     * Record that data traffic occurred in the given time range. Will
-     * distribute across internal buckets, creating new buckets as needed.
-     * @hide
-     */
-    public void recordData(long start, long end, NetworkStats.Entry entry) {
-        long rxBytes = entry.rxBytes;
-        long rxPackets = entry.rxPackets;
-        long txBytes = entry.txBytes;
-        long txPackets = entry.txPackets;
-        long operations = entry.operations;
-
-        if (entry.isNegative()) {
-            throw new IllegalArgumentException("tried recording negative data");
-        }
-        if (entry.isEmpty()) {
-            return;
-        }
-
-        // create any buckets needed by this range
-        ensureBuckets(start, end);
-        // Return fast if there is still no entry. This would typically happen when the start,
-        // end or duration are not valid values, e.g. start > end, negative duration value, etc.
-        if (bucketCount == 0) return;
-
-        // distribute data usage into buckets
-        long duration = end - start;
-        final int startIndex = getIndexAfter(end);
-        for (int i = startIndex; i >= 0; i--) {
-            final long curStart = bucketStart[i];
-            final long curEnd = curStart + bucketDuration;
-
-            // bucket is older than record; we're finished
-            if (curEnd < start) break;
-            // bucket is newer than record; keep looking
-            if (curStart > end) continue;
-
-            final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
-            if (overlap <= 0) continue;
-
-            // integer math each time is faster than floating point
-            final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration);
-            final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration);
-            final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration);
-            final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration);
-            final long fracOperations = multiplySafeByRational(operations, overlap, duration);
-
-
-            addLong(activeTime, i, overlap);
-            addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes;
-            addLong(this.rxPackets, i, fracRxPackets); rxPackets -= fracRxPackets;
-            addLong(this.txBytes, i, fracTxBytes); txBytes -= fracTxBytes;
-            addLong(this.txPackets, i, fracTxPackets); txPackets -= fracTxPackets;
-            addLong(this.operations, i, fracOperations); operations -= fracOperations;
-
-            duration -= overlap;
-        }
-
-        totalBytes += entry.rxBytes + entry.txBytes;
-    }
-
-    /**
-     * Record an entire {@link NetworkStatsHistory} into this history. Usually
-     * for combining together stats for external reporting.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public void recordEntireHistory(NetworkStatsHistory input) {
-        recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE);
-    }
-
-    /**
-     * Record given {@link NetworkStatsHistory} into this history, copying only
-     * buckets that atomically occur in the inclusive time range. Doesn't
-     * interpolate across partial buckets.
-     * @hide
-     */
-    public void recordHistory(NetworkStatsHistory input, long start, long end) {
-        final NetworkStats.Entry entry = new NetworkStats.Entry(
-                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
-        for (int i = 0; i < input.bucketCount; i++) {
-            final long bucketStart = input.bucketStart[i];
-            final long bucketEnd = bucketStart + input.bucketDuration;
-
-            // skip when bucket is outside requested range
-            if (bucketStart < start || bucketEnd > end) continue;
-
-            entry.rxBytes = getLong(input.rxBytes, i, 0L);
-            entry.rxPackets = getLong(input.rxPackets, i, 0L);
-            entry.txBytes = getLong(input.txBytes, i, 0L);
-            entry.txPackets = getLong(input.txPackets, i, 0L);
-            entry.operations = getLong(input.operations, i, 0L);
-
-            recordData(bucketStart, bucketEnd, entry);
-        }
-    }
-
-    /**
-     * Ensure that buckets exist for given time range, creating as needed.
-     */
-    private void ensureBuckets(long start, long end) {
-        // normalize incoming range to bucket boundaries
-        start -= start % bucketDuration;
-        end += (bucketDuration - (end % bucketDuration)) % bucketDuration;
-
-        for (long now = start; now < end; now += bucketDuration) {
-            // try finding existing bucket
-            final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now);
-            if (index < 0) {
-                // bucket missing, create and insert
-                insertBucket(~index, now);
-            }
-        }
-    }
-
-    /**
-     * Insert new bucket at requested index and starting time.
-     */
-    private void insertBucket(int index, long start) {
-        // create more buckets when needed
-        if (bucketCount >= bucketStart.length) {
-            final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
-            bucketStart = Arrays.copyOf(bucketStart, newLength);
-            if (activeTime != null) activeTime = Arrays.copyOf(activeTime, newLength);
-            if (rxBytes != null) rxBytes = Arrays.copyOf(rxBytes, newLength);
-            if (rxPackets != null) rxPackets = Arrays.copyOf(rxPackets, newLength);
-            if (txBytes != null) txBytes = Arrays.copyOf(txBytes, newLength);
-            if (txPackets != null) txPackets = Arrays.copyOf(txPackets, newLength);
-            if (operations != null) operations = Arrays.copyOf(operations, newLength);
-        }
-
-        // create gap when inserting bucket in middle
-        if (index < bucketCount) {
-            final int dstPos = index + 1;
-            final int length = bucketCount - index;
-
-            System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
-            if (activeTime != null) System.arraycopy(activeTime, index, activeTime, dstPos, length);
-            if (rxBytes != null) System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
-            if (rxPackets != null) System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
-            if (txBytes != null) System.arraycopy(txBytes, index, txBytes, dstPos, length);
-            if (txPackets != null) System.arraycopy(txPackets, index, txPackets, dstPos, length);
-            if (operations != null) System.arraycopy(operations, index, operations, dstPos, length);
-        }
-
-        bucketStart[index] = start;
-        setLong(activeTime, index, 0L);
-        setLong(rxBytes, index, 0L);
-        setLong(rxPackets, index, 0L);
-        setLong(txBytes, index, 0L);
-        setLong(txPackets, index, 0L);
-        setLong(operations, index, 0L);
-        bucketCount++;
-    }
-
-    /**
-     * Clear all data stored in this object.
-     * @hide
-     */
-    public void clear() {
-        bucketStart = EmptyArray.LONG;
-        if (activeTime != null) activeTime = EmptyArray.LONG;
-        if (rxBytes != null) rxBytes = EmptyArray.LONG;
-        if (rxPackets != null) rxPackets = EmptyArray.LONG;
-        if (txBytes != null) txBytes = EmptyArray.LONG;
-        if (txPackets != null) txPackets = EmptyArray.LONG;
-        if (operations != null) operations = EmptyArray.LONG;
-        bucketCount = 0;
-        totalBytes = 0;
-    }
-
-    /**
-     * Remove buckets older than requested cutoff.
-     * @hide
-     */
-    public void removeBucketsBefore(long cutoff) {
-        // TODO: Consider use getIndexBefore.
-        int i;
-        for (i = 0; i < bucketCount; i++) {
-            final long curStart = bucketStart[i];
-            final long curEnd = curStart + bucketDuration;
-
-            // cutoff happens before or during this bucket; everything before
-            // this bucket should be removed.
-            if (curEnd > cutoff) break;
-        }
-
-        if (i > 0) {
-            final int length = bucketStart.length;
-            bucketStart = Arrays.copyOfRange(bucketStart, i, length);
-            if (activeTime != null) activeTime = Arrays.copyOfRange(activeTime, i, length);
-            if (rxBytes != null) rxBytes = Arrays.copyOfRange(rxBytes, i, length);
-            if (rxPackets != null) rxPackets = Arrays.copyOfRange(rxPackets, i, length);
-            if (txBytes != null) txBytes = Arrays.copyOfRange(txBytes, i, length);
-            if (txPackets != null) txPackets = Arrays.copyOfRange(txPackets, i, length);
-            if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
-            bucketCount -= i;
-
-            totalBytes = 0;
-            if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes);
-            if (txBytes != null) totalBytes += CollectionUtils.total(txBytes);
-        }
-    }
-
-    /**
-     * Return interpolated data usage across the requested range. Interpolates
-     * across buckets, so values may be rounded slightly.
-     *
-     * <p>If the active bucket is not completed yet, it returns the proportional value of it
-     * based on its duration and the {@code end} param.
-     *
-     * @param start - start of the range, timestamp in milliseconds since the epoch.
-     * @param end - end of the range, timestamp in milliseconds since the epoch.
-     * @param recycle - entry instance for performance, could be null.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Entry getValues(long start, long end, Entry recycle) {
-        return getValues(start, end, Long.MAX_VALUE, recycle);
-    }
-
-    /**
-     * Return interpolated data usage across the requested range. Interpolates
-     * across buckets, so values may be rounded slightly.
-     *
-     * @param start - start of the range, timestamp in milliseconds since the epoch.
-     * @param end - end of the range, timestamp in milliseconds since the epoch.
-     * @param now - current timestamp in milliseconds since the epoch (wall clock).
-     * @param recycle - entry instance for performance, could be null.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Entry getValues(long start, long end, long now, Entry recycle) {
-        final Entry entry = recycle != null ? recycle : new Entry();
-        entry.bucketDuration = end - start;
-        entry.bucketStart = start;
-        entry.activeTime = activeTime != null ? 0 : UNKNOWN;
-        entry.rxBytes = rxBytes != null ? 0 : UNKNOWN;
-        entry.rxPackets = rxPackets != null ? 0 : UNKNOWN;
-        entry.txBytes = txBytes != null ? 0 : UNKNOWN;
-        entry.txPackets = txPackets != null ? 0 : UNKNOWN;
-        entry.operations = operations != null ? 0 : UNKNOWN;
-
-        // Return fast if there is no entry.
-        if (bucketCount == 0) return entry;
-
-        final int startIndex = getIndexAfter(end);
-        for (int i = startIndex; i >= 0; i--) {
-            final long curStart = bucketStart[i];
-            long curEnd = curStart + bucketDuration;
-
-            // bucket is older than request; we're finished
-            if (curEnd <= start) break;
-            // bucket is newer than request; keep looking
-            if (curStart >= end) continue;
-
-            // the active bucket is shorter then a normal completed bucket
-            if (curEnd > now) curEnd = now;
-            // usually this is simply bucketDuration
-            final long bucketSpan = curEnd - curStart;
-            // prevent division by zero
-            if (bucketSpan <= 0) continue;
-
-            final long overlapEnd = curEnd < end ? curEnd : end;
-            final long overlapStart = curStart > start ? curStart : start;
-            final long overlap = overlapEnd - overlapStart;
-            if (overlap <= 0) continue;
-
-            // integer math each time is faster than floating point
-            if (activeTime != null) {
-                entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan);
-            }
-            if (rxBytes != null) {
-                entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan);
-            }
-            if (rxPackets != null) {
-                entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan);
-            }
-            if (txBytes != null) {
-                entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan);
-            }
-            if (txPackets != null) {
-                entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan);
-            }
-            if (operations != null) {
-                entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan);
-            }
-        }
-        return entry;
-    }
-
-    /**
-     * @deprecated only for temporary testing
-     * @hide
-     */
-    @Deprecated
-    public void generateRandom(long start, long end, long bytes) {
-        final Random r = new Random();
-
-        final float fractionRx = r.nextFloat();
-        final long rxBytes = (long) (bytes * fractionRx);
-        final long txBytes = (long) (bytes * (1 - fractionRx));
-
-        final long rxPackets = rxBytes / 1024;
-        final long txPackets = txBytes / 1024;
-        final long operations = rxBytes / 2048;
-
-        generateRandom(start, end, rxBytes, rxPackets, txBytes, txPackets, operations, r);
-    }
-
-    /**
-     * @deprecated only for temporary testing
-     * @hide
-     */
-    @Deprecated
-    public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
-            long txPackets, long operations, Random r) {
-        ensureBuckets(start, end);
-
-        final NetworkStats.Entry entry = new NetworkStats.Entry(
-                IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
-        while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128
-                || operations > 32) {
-            final long curStart = randomLong(r, start, end);
-            final long curEnd = curStart + randomLong(r, 0, (end - curStart) / 2);
-
-            entry.rxBytes = randomLong(r, 0, rxBytes);
-            entry.rxPackets = randomLong(r, 0, rxPackets);
-            entry.txBytes = randomLong(r, 0, txBytes);
-            entry.txPackets = randomLong(r, 0, txPackets);
-            entry.operations = randomLong(r, 0, operations);
-
-            rxBytes -= entry.rxBytes;
-            rxPackets -= entry.rxPackets;
-            txBytes -= entry.txBytes;
-            txPackets -= entry.txPackets;
-            operations -= entry.operations;
-
-            recordData(curStart, curEnd, entry);
-        }
-    }
-
-    /** @hide */
-    public static long randomLong(Random r, long start, long end) {
-        return (long) (start + (r.nextFloat() * (end - start)));
-    }
-
-    /**
-     * Quickly determine if this history intersects with given window.
-     * @hide
-     */
-    public boolean intersects(long start, long end) {
-        final long dataStart = getStart();
-        final long dataEnd = getEnd();
-        if (start >= dataStart && start <= dataEnd) return true;
-        if (end >= dataStart && end <= dataEnd) return true;
-        if (dataStart >= start && dataStart <= end) return true;
-        if (dataEnd >= start && dataEnd <= end) return true;
-        return false;
-    }
-
-    /** @hide */
-    public void dump(IndentingPrintWriter pw, boolean fullHistory) {
-        pw.print("NetworkStatsHistory: bucketDuration=");
-        pw.println(bucketDuration / SECOND_IN_MILLIS);
-        pw.increaseIndent();
-
-        final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32);
-        if (start > 0) {
-            pw.print("(omitting "); pw.print(start); pw.println(" buckets)");
-        }
-
-        for (int i = start; i < bucketCount; i++) {
-            pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS);
-            if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); }
-            if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); }
-            if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); }
-            if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); }
-            if (operations != null) { pw.print(" op="); pw.print(operations[i]); }
-            pw.println();
-        }
-
-        pw.decreaseIndent();
-    }
-
-    /** @hide */
-    public void dumpCheckin(PrintWriter pw) {
-        pw.print("d,");
-        pw.print(bucketDuration / SECOND_IN_MILLIS);
-        pw.println();
-
-        for (int i = 0; i < bucketCount; i++) {
-            pw.print("b,");
-            pw.print(bucketStart[i] / SECOND_IN_MILLIS); pw.print(',');
-            if (rxBytes != null) { pw.print(rxBytes[i]); } else { pw.print("*"); } pw.print(',');
-            if (rxPackets != null) { pw.print(rxPackets[i]); } else { pw.print("*"); } pw.print(',');
-            if (txBytes != null) { pw.print(txBytes[i]); } else { pw.print("*"); } pw.print(',');
-            if (txPackets != null) { pw.print(txPackets[i]); } else { pw.print("*"); } pw.print(',');
-            if (operations != null) { pw.print(operations[i]); } else { pw.print("*"); }
-            pw.println();
-        }
-    }
-
-    /** @hide */
-    public void dumpDebug(ProtoOutputStream proto, long tag) {
-        final long start = proto.start(tag);
-
-        proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration);
-
-        for (int i = 0; i < bucketCount; i++) {
-            final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS);
-
-            proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS,
-                    bucketStart[i]);
-            dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i);
-            dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i);
-            dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i);
-            dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i);
-            dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i);
-
-            proto.end(startBucket);
-        }
-
-        proto.end(start);
-    }
-
-    private static void dumpDebug(ProtoOutputStream proto, long tag, long[] array, int index) {
-        if (array != null) {
-            proto.write(tag, array[index]);
-        }
-    }
-
-    @Override
-    public String toString() {
-        final CharArrayWriter writer = new CharArrayWriter();
-        dump(new IndentingPrintWriter(writer, "  "), false);
-        return writer.toString();
-    }
-
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
-        @Override
-        public NetworkStatsHistory createFromParcel(Parcel in) {
-            return new NetworkStatsHistory(in);
-        }
-
-        @Override
-        public NetworkStatsHistory[] newArray(int size) {
-            return new NetworkStatsHistory[size];
-        }
-    };
-
-    private static long getLong(long[] array, int i, long value) {
-        return array != null ? array[i] : value;
-    }
-
-    private static void setLong(long[] array, int i, long value) {
-        if (array != null) array[i] = value;
-    }
-
-    private static void addLong(long[] array, int i, long value) {
-        if (array != null) array[i] += value;
-    }
-
-    /** @hide */
-    public int estimateResizeBuckets(long newBucketDuration) {
-        return (int) (size() * getBucketDuration() / newBucketDuration);
-    }
-
-    /**
-     * Utility methods for interacting with {@link DataInputStream} and
-     * {@link DataOutputStream}, mostly dealing with writing partial arrays.
-     * @hide
-     */
-    public static class DataStreamUtils {
-        @Deprecated
-        public static long[] readFullLongArray(DataInput in) throws IOException {
-            final int size = in.readInt();
-            if (size < 0) throw new ProtocolException("negative array size");
-            final long[] values = new long[size];
-            for (int i = 0; i < values.length; i++) {
-                values[i] = in.readLong();
-            }
-            return values;
-        }
-
-        /**
-         * Read variable-length {@link Long} using protobuf-style approach.
-         */
-        public static long readVarLong(DataInput in) throws IOException {
-            int shift = 0;
-            long result = 0;
-            while (shift < 64) {
-                byte b = in.readByte();
-                result |= (long) (b & 0x7F) << shift;
-                if ((b & 0x80) == 0)
-                    return result;
-                shift += 7;
-            }
-            throw new ProtocolException("malformed long");
-        }
-
-        /**
-         * Write variable-length {@link Long} using protobuf-style approach.
-         */
-        public static void writeVarLong(DataOutput out, long value) throws IOException {
-            while (true) {
-                if ((value & ~0x7FL) == 0) {
-                    out.writeByte((int) value);
-                    return;
-                } else {
-                    out.writeByte(((int) value & 0x7F) | 0x80);
-                    value >>>= 7;
-                }
-            }
-        }
-
-        public static long[] readVarLongArray(DataInput in) throws IOException {
-            final int size = in.readInt();
-            if (size == -1) return null;
-            if (size < 0) throw new ProtocolException("negative array size");
-            final long[] values = new long[size];
-            for (int i = 0; i < values.length; i++) {
-                values[i] = readVarLong(in);
-            }
-            return values;
-        }
-
-        public static void writeVarLongArray(DataOutput out, long[] values, int size)
-                throws IOException {
-            if (values == null) {
-                out.writeInt(-1);
-                return;
-            }
-            if (size > values.length) {
-                throw new IllegalArgumentException("size larger than length");
-            }
-            out.writeInt(size);
-            for (int i = 0; i < size; i++) {
-                writeVarLong(out, values[i]);
-            }
-        }
-    }
-
-    /**
-     * Utility methods for interacting with {@link Parcel} structures, mostly
-     * dealing with writing partial arrays.
-     * @hide
-     */
-    public static class ParcelUtils {
-        public static long[] readLongArray(Parcel in) {
-            final int size = in.readInt();
-            if (size == -1) return null;
-            final long[] values = new long[size];
-            for (int i = 0; i < values.length; i++) {
-                values[i] = in.readLong();
-            }
-            return values;
-        }
-
-        public static void writeLongArray(Parcel out, long[] values, int size) {
-            if (values == null) {
-                out.writeInt(-1);
-                return;
-            }
-            if (size > values.length) {
-                throw new IllegalArgumentException("size larger than length");
-            }
-            out.writeInt(size);
-            for (int i = 0; i < size; i++) {
-                out.writeLong(values[i]);
-            }
-        }
-    }
-
-    /**
-     * Builder class for {@link NetworkStatsHistory}.
-     */
-    public static final class Builder {
-        private final long mBucketDuration;
-        private final List<Long> mBucketStart;
-        private final List<Long> mActiveTime;
-        private final List<Long> mRxBytes;
-        private final List<Long> mRxPackets;
-        private final List<Long> mTxBytes;
-        private final List<Long> mTxPackets;
-        private final List<Long> mOperations;
-
-        /**
-         * Creates a new Builder with given bucket duration and initial capacity to construct
-         * {@link NetworkStatsHistory} objects.
-         *
-         * @param bucketDuration Duration of the buckets of the object, in milliseconds.
-         * @param initialCapacity Estimated number of records.
-         */
-        public Builder(long bucketDuration, int initialCapacity) {
-            mBucketDuration = bucketDuration;
-            mBucketStart = new ArrayList<>(initialCapacity);
-            mActiveTime = new ArrayList<>(initialCapacity);
-            mRxBytes = new ArrayList<>(initialCapacity);
-            mRxPackets = new ArrayList<>(initialCapacity);
-            mTxBytes = new ArrayList<>(initialCapacity);
-            mTxPackets = new ArrayList<>(initialCapacity);
-            mOperations = new ArrayList<>(initialCapacity);
-        }
-
-        /**
-         * Add an {@link Entry} into the {@link NetworkStatsHistory} instance.
-         *
-         * @param entry The target {@link Entry} object.
-         * @return The builder object.
-         */
-        @NonNull
-        public Builder addEntry(@NonNull Entry entry) {
-            mBucketStart.add(entry.bucketStart);
-            mActiveTime.add(entry.activeTime);
-            mRxBytes.add(entry.rxBytes);
-            mRxPackets.add(entry.rxPackets);
-            mTxBytes.add(entry.txBytes);
-            mTxPackets.add(entry.txPackets);
-            mOperations.add(entry.operations);
-            return this;
-        }
-
-        private static long sum(@NonNull List<Long> list) {
-            long sum = 0;
-            for (long entry : list) {
-                sum += entry;
-            }
-            return sum;
-        }
-
-        /**
-         * Builds the instance of the {@link NetworkStatsHistory}.
-         *
-         * @return the built instance of {@link NetworkStatsHistory}.
-         */
-        @NonNull
-        public NetworkStatsHistory build() {
-            return new NetworkStatsHistory(mBucketDuration,
-                    CollectionUtils.toLongArray(mBucketStart),
-                    CollectionUtils.toLongArray(mActiveTime),
-                    CollectionUtils.toLongArray(mRxBytes),
-                    CollectionUtils.toLongArray(mRxPackets),
-                    CollectionUtils.toLongArray(mTxBytes),
-                    CollectionUtils.toLongArray(mTxPackets),
-                    CollectionUtils.toLongArray(mOperations),
-                    mBucketStart.size(),
-                    sum(mRxBytes) + sum(mTxBytes));
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
deleted file mode 100644
index 7b5afd7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ /dev/null
@@ -1,1119 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
-import static android.net.ConnectivityManager.TYPE_ETHERNET;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_PROXY;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-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;
-import static android.net.NetworkStats.METERED_ALL;
-import static android.net.NetworkStats.METERED_NO;
-import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_ALL;
-import static android.net.NetworkStats.ROAMING_NO;
-import static android.net.NetworkStats.ROAMING_YES;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.usage.NetworkStatsManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.wifi.WifiInfo;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.ArraySet;
-
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.NetworkIdentityUtils;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
-import java.util.Comparator;
-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
- * statistics. (It should probably have been named {@code NetworkPredicate}.)
- *
- * @hide
- */
-@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_PROXY,
-            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 ConnectivityManager#TYPE_PROXY} as the legacy
-     * network type.
-     */
-    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;
-
-    // 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.
-     */
-    public static final int NETWORK_TYPE_ALL = -1;
-
-    /** @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).
-     */
-    public static final int OEM_MANAGED_ALL = -1;
-    /**
-     * Value to match networks which are not OEM managed.
-     */
-    public static final int OEM_MANAGED_NO = OEM_NONE;
-    /**
-     * Value to match any OEM managed network.
-     */
-    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) {
-            case MATCH_MOBILE:
-            case MATCH_WIFI:
-            case MATCH_ETHERNET:
-            case MATCH_MOBILE_WILDCARD:
-            case MATCH_WIFI_WILDCARD:
-            case MATCH_BLUETOOTH:
-            case MATCH_PROXY:
-            case MATCH_CARRIER:
-                return true;
-
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
-     * the given IMSI.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
-        return new NetworkTemplate(MATCH_MOBILE, subscriberId, null);
-    }
-
-    /**
-     * 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,
-            int ratType, int metered) {
-        if (TextUtils.isEmpty(subscriberId)) {
-            return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */,
-                    null /* matchSubscriberIds */,
-                    new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL,
-                    DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
-                    NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-        }
-        return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[] { subscriberId },
-                new String[0] /* matchWifiNetworkKeys */,
-                metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
-                NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-    }
-
-    /**
-     * 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() {
-        return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
-    }
-
-    /**
-     * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
-     * regardless of key of the wifi network.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static NetworkTemplate buildTemplateWifiWildcard() {
-        // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL
-        // and SUBSCRIBER_ID_MATCH_RULE_ALL.
-        return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
-    }
-
-    /** @hide */
-    @Deprecated
-    @UnsupportedAppUsage
-    public static NetworkTemplate buildTemplateWifi() {
-        return buildTemplateWifiWildcard();
-    }
-
-    /**
-     * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
-     * given key of the wifi network.
-     *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
-     *                  to know details about the key.
-     * @hide
-     */
-    public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) {
-        Objects.requireNonNull(wifiNetworkKey);
-        return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */,
-                new String[] { null } /* matchSubscriberIds */,
-                new String[] { wifiNetworkKey }, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL);
-    }
-
-    /**
-     * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given
-     * key of the wifi network and IMSI.
-     *
-     * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
-     * of key of the wifi network.
-     *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
-     *                  to know details about the key.
-     * @param subscriberId the IMSI associated to this wifi network.
-     *
-     * @hide
-     */
-    public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey,
-            @Nullable String subscriberId) {
-        return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId },
-                wifiNetworkKey != null
-                        ? new String[] { wifiNetworkKey } : new String[0],
-                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-    }
-
-    /**
-     * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style
-     * networks together.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static NetworkTemplate buildTemplateEthernet() {
-        return new NetworkTemplate(MATCH_ETHERNET, null, null);
-    }
-
-    /**
-     * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style
-     * networks together.
-     *
-     * @hide
-     */
-    public static NetworkTemplate buildTemplateBluetooth() {
-        return new NetworkTemplate(MATCH_BLUETOOTH, null, null);
-    }
-
-    /**
-     * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style
-     * networks together.
-     *
-     * @hide
-     */
-    public static NetworkTemplate buildTemplateProxy() {
-        return new NetworkTemplate(MATCH_PROXY, null, null);
-    }
-
-    /**
-     * Template to match all metered carrier networks with the given IMSI.
-     *
-     * @hide
-     */
-    public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
-        Objects.requireNonNull(subscriberId);
-        return new NetworkTemplate(MATCH_CARRIER, subscriberId,
-                new String[] { subscriberId },
-                new String[0] /* matchWifiNetworkKeys */,
-                METERED_YES, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-    }
-
-    private final int mMatchRule;
-    private final String mSubscriberId;
-
-    /**
-     * Ugh, templates are designed to target a single subscriber, but we might
-     * need to match several "merged" subscribers. These are the subscribers
-     * that should be considered to match this template.
-     * <p>
-     * Since the merge set is dynamic, it should <em>not</em> be persisted or
-     * used for determining equality.
-     */
-    private final String[] mMatchSubscriberIds;
-
-    @NonNull
-    private final String[] mMatchWifiNetworkKeys;
-
-    // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*.
-    private final int mMetered;
-    private final int mRoaming;
-    private final int mDefaultNetwork;
-    private final int mRatType;
-    /**
-     * The subscriber Id match rule defines how the template should match networks with
-     * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
-     */
-    private final int mSubscriberIdMatchRule;
-
-    // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
-    private final int mOemManaged;
-
-    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 (subscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL) {
-                    throw new IllegalArgumentException("Invalid SubscriberIdMatchRule "
-                            + "on match rule: " + getMatchRuleName(matchRule));
-                }
-                return;
-            default:
-                return;
-        }
-    }
-
-    /** @hide */
-    // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
-    @UnsupportedAppUsage
-    public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) {
-        this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey);
-    }
-
-    /** @hide */
-    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String wifiNetworkKey) {
-        // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
-        // to metered networks. It is now possible to match mobile with any meteredness, but
-        // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
-        //constructor passes METERED_YES for these types.
-        this(matchRule, subscriberId, matchSubscriberIds,
-                wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
-                (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
-                : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
-                OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-    }
-
-    /** @hide */
-    // TODO: Remove it after updating all of the caller.
-    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType,
-            int oemManaged) {
-        this(matchRule, subscriberId, matchSubscriberIds,
-                wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
-                metered, roaming, defaultNetwork, ratType, oemManaged,
-                NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
-    }
-
-    /** @hide */
-    public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
-            String[] matchWifiNetworkKeys, int metered, int roaming,
-            int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
-        Objects.requireNonNull(matchWifiNetworkKeys);
-        mMatchRule = matchRule;
-        mSubscriberId = subscriberId;
-        // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when
-        // mSubscriberId is null
-        mMatchSubscriberIds = matchSubscriberIds;
-        mMatchWifiNetworkKeys = matchWifiNetworkKeys;
-        mMetered = metered;
-        mRoaming = roaming;
-        mDefaultNetwork = defaultNetwork;
-        mRatType = ratType;
-        mOemManaged = oemManaged;
-        mSubscriberIdMatchRule = subscriberIdMatchRule;
-        checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
-        if (!isKnownMatchRule(matchRule)) {
-            throw new IllegalArgumentException("Unknown network template rule " + matchRule
-                    + " will not match any identity.");
-        }
-    }
-
-    private NetworkTemplate(Parcel in) {
-        mMatchRule = in.readInt();
-        mSubscriberId = in.readString();
-        mMatchSubscriberIds = in.createStringArray();
-        mMatchWifiNetworkKeys = in.createStringArray();
-        mMetered = in.readInt();
-        mRoaming = in.readInt();
-        mDefaultNetwork = in.readInt();
-        mRatType = in.readInt();
-        mOemManaged = in.readInt();
-        mSubscriberIdMatchRule = in.readInt();
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mMatchRule);
-        dest.writeString(mSubscriberId);
-        dest.writeStringArray(mMatchSubscriberIds);
-        dest.writeStringArray(mMatchWifiNetworkKeys);
-        dest.writeInt(mMetered);
-        dest.writeInt(mRoaming);
-        dest.writeInt(mDefaultNetwork);
-        dest.writeInt(mRatType);
-        dest.writeInt(mOemManaged);
-        dest.writeInt(mSubscriberIdMatchRule);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public String toString() {
-        final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
-        builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
-        if (mSubscriberId != null) {
-            builder.append(", subscriberId=").append(
-                    NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
-        }
-        if (mMatchSubscriberIds != null) {
-            builder.append(", matchSubscriberIds=").append(
-                    Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds)));
-        }
-        builder.append(", matchWifiNetworkKeys=").append(Arrays.toString(mMatchWifiNetworkKeys));
-        if (mMetered != METERED_ALL) {
-            builder.append(", metered=").append(NetworkStats.meteredToString(mMetered));
-        }
-        if (mRoaming != ROAMING_ALL) {
-            builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming));
-        }
-        if (mDefaultNetwork != DEFAULT_NETWORK_ALL) {
-            builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
-                    mDefaultNetwork));
-        }
-        if (mRatType != NETWORK_TYPE_ALL) {
-            builder.append(", ratType=").append(mRatType);
-        }
-        if (mOemManaged != OEM_MANAGED_ALL) {
-            builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
-        }
-        builder.append(", subscriberIdMatchRule=")
-                .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
-        return builder.toString();
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
-                mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule);
-    }
-
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (obj instanceof NetworkTemplate) {
-            final NetworkTemplate other = (NetworkTemplate) obj;
-            return mMatchRule == other.mMatchRule
-                    && Objects.equals(mSubscriberId, other.mSubscriberId)
-                    && mMetered == other.mMetered
-                    && mRoaming == other.mRoaming
-                    && mDefaultNetwork == other.mDefaultNetwork
-                    && mRatType == other.mRatType
-                    && mOemManaged == other.mOemManaged
-                    && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
-                    && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
-        }
-        return false;
-    }
-
-    private static String subscriberIdMatchRuleToString(int rule) {
-        switch (rule) {
-            case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT:
-                return "EXACT_MATCH";
-            case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL:
-                return "ALL";
-            default:
-                return "Unknown rule " + rule;
-        }
-    }
-
-    /** @hide */
-    public boolean isMatchRuleMobile() {
-        switch (mMatchRule) {
-            case MATCH_MOBILE:
-            case MATCH_MOBILE_WILDCARD:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * 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 MATCH_WIFI;
-            default:
-                return mMatchRule;
-        }
-    }
-
-    /**
-     * Get subscriber Id of the template.
-     * @hide
-     */
-    @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 the set of Wifi Network Keys of the template.
-     * See {@link WifiInfo#getNetworkKey()}.
-     */
-    @NonNull
-    public Set<String> getWifiNetworkKeys() {
-        return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys));
-    }
-
-    /** @hide */
-    // TODO: Remove this and replace all callers with {@link #getWifiNetworkKeys()}.
-    @Nullable
-    public String getNetworkId() {
-        return getWifiNetworkKeys().isEmpty() ? null : getWifiNetworkKeys().iterator().next();
-    }
-
-    /**
-     * 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 mRatType;
-    }
-
-    /**
-     * 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
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public boolean matches(@NonNull NetworkIdentity ident) {
-        Objects.requireNonNull(ident);
-        if (!matchesMetered(ident)) return false;
-        if (!matchesRoaming(ident)) return false;
-        if (!matchesDefaultNetwork(ident)) return false;
-        if (!matchesOemNetwork(ident)) return false;
-
-        switch (mMatchRule) {
-            case MATCH_MOBILE:
-                return matchesMobile(ident);
-            case MATCH_WIFI:
-                return matchesWifi(ident);
-            case MATCH_ETHERNET:
-                return matchesEthernet(ident);
-            case MATCH_MOBILE_WILDCARD:
-                return matchesMobileWildcard(ident);
-            case MATCH_WIFI_WILDCARD:
-                return matchesWifiWildcard(ident);
-            case MATCH_BLUETOOTH:
-                return matchesBluetooth(ident);
-            case MATCH_PROXY:
-                return matchesProxy(ident);
-            case MATCH_CARRIER:
-                return matchesCarrier(ident);
-            default:
-                // We have no idea what kind of network template we are, so we
-                // just claim not to match anything.
-                return false;
-        }
-    }
-
-    private boolean matchesMetered(NetworkIdentity ident) {
-        return (mMetered == METERED_ALL)
-            || (mMetered == METERED_YES && ident.mMetered)
-            || (mMetered == METERED_NO && !ident.mMetered);
-    }
-
-    private boolean matchesRoaming(NetworkIdentity ident) {
-        return (mRoaming == ROAMING_ALL)
-            || (mRoaming == ROAMING_YES && ident.mRoaming)
-            || (mRoaming == ROAMING_NO && !ident.mRoaming);
-    }
-
-    private boolean matchesDefaultNetwork(NetworkIdentity ident) {
-        return (mDefaultNetwork == DEFAULT_NETWORK_ALL)
-            || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork)
-            || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
-    }
-
-    private boolean matchesOemNetwork(NetworkIdentity ident) {
-        return (mOemManaged == OEM_MANAGED_ALL)
-            || (mOemManaged == OEM_MANAGED_YES
-                    && ident.mOemManaged != OEM_NONE)
-            || (mOemManaged == ident.mOemManaged);
-    }
-
-    private boolean matchesCollapsedRatType(NetworkIdentity ident) {
-        return mRatType == NETWORK_TYPE_ALL
-                || NetworkStatsManager.getCollapsedRatType(mRatType)
-                == NetworkStatsManager.getCollapsedRatType(ident.mRatType);
-    }
-
-    /**
-     * 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 == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
-                || CollectionUtils.contains(mMatchSubscriberIds, subscriberId);
-    }
-
-    /**
-     * Check if network matches key of the wifi network.
-     * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
-     * empty.
-     *
-     * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
-     *                  to know details about the key.
-     */
-    private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
-        Objects.requireNonNull(wifiNetworkKey);
-        return CollectionUtils.isEmpty(mMatchWifiNetworkKeys)
-                || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey);
-    }
-
-    /**
-     * Check if mobile network matches IMSI.
-     */
-    private boolean matchesMobile(NetworkIdentity ident) {
-        if (ident.mType == TYPE_WIMAX) {
-            // TODO: consider matching against WiMAX subscriber identity
-            return true;
-        } else {
-            return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds)
-                    && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
-                    && matchesCollapsedRatType(ident);
-        }
-    }
-
-    /**
-     * Check if matches Wi-Fi network template.
-     */
-    private boolean matchesWifi(NetworkIdentity ident) {
-        switch (ident.mType) {
-            case TYPE_WIFI:
-                return matchesSubscriberId(ident.mSubscriberId)
-                        && matchesWifiNetworkKey(ident.mWifiNetworkKey);
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Check if matches Ethernet network template.
-     */
-    private boolean matchesEthernet(NetworkIdentity ident) {
-        if (ident.mType == TYPE_ETHERNET) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Check if matches carrier network. The carrier networks means it includes the subscriberId.
-     */
-    private boolean matchesCarrier(NetworkIdentity ident) {
-        return ident.mSubscriberId != null
-                && !CollectionUtils.isEmpty(mMatchSubscriberIds)
-                && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
-    }
-
-    private boolean matchesMobileWildcard(NetworkIdentity ident) {
-        if (ident.mType == TYPE_WIMAX) {
-            return true;
-        } else {
-            return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
-        }
-    }
-
-    private boolean matchesWifiWildcard(NetworkIdentity ident) {
-        switch (ident.mType) {
-            case TYPE_WIFI:
-            case TYPE_WIFI_P2P:
-                return true;
-            default:
-                return false;
-        }
-    }
-
-    /**
-     * Check if matches Bluetooth network template.
-     */
-    private boolean matchesBluetooth(NetworkIdentity ident) {
-        if (ident.mType == TYPE_BLUETOOTH) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Check if matches Proxy network template.
-     */
-    private boolean matchesProxy(NetworkIdentity ident) {
-        return ident.mType == TYPE_PROXY;
-    }
-
-    private static String getMatchRuleName(int matchRule) {
-        switch (matchRule) {
-            case MATCH_MOBILE:
-                return "MOBILE";
-            case MATCH_WIFI:
-                return "WIFI";
-            case MATCH_ETHERNET:
-                return "ETHERNET";
-            case MATCH_MOBILE_WILDCARD:
-                return "MOBILE_WILDCARD";
-            case MATCH_WIFI_WILDCARD:
-                return "WIFI_WILDCARD";
-            case MATCH_BLUETOOTH:
-                return "BLUETOOTH";
-            case MATCH_PROXY:
-                return "PROXY";
-            case MATCH_CARRIER:
-                return "CARRIER";
-            default:
-                return "UNKNOWN(" + matchRule + ")";
-        }
-    }
-
-    private static String getOemManagedNames(int oemManaged) {
-        switch (oemManaged) {
-            case OEM_MANAGED_ALL:
-                return "OEM_MANAGED_ALL";
-            case OEM_MANAGED_NO:
-                return "OEM_MANAGED_NO";
-            case OEM_MANAGED_YES:
-                return "OEM_MANAGED_YES";
-            default:
-                return NetworkIdentity.getOemManagedNames(oemManaged);
-        }
-    }
-
-    /**
-     * Examine the given template and normalize it.
-     * We pick the "lowest" merged subscriber as the primary
-     * for key purposes, and expand the template to match all other merged
-     * subscribers.
-     * <p>
-     * 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.
-     * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
-        return normalize(template, Arrays.<String[]>asList(merged));
-    }
-
-    /**
-     * Examine the given template and normalize it.
-     * We pick the "lowest" merged subscriber as the primary
-     * for key purposes, and expand the template to match all other merged
-     * subscribers.
-     *
-     * There can be multiple merged subscriberIds for multi-SIM devices.
-     *
-     * <p>
-     * 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:
-        // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network.
-        // The TYPE_CARRIER means that the network associate to specific carrier network.
-
-        if (template.mSubscriberId == null) return template;
-
-        for (String[] merged : mergedList) {
-            if (CollectionUtils.contains(merged, template.mSubscriberId)) {
-                // Requested template subscriber is part of the merge group; return
-                // a template that matches all merged subscribers.
-                final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys;
-                return new NetworkTemplate(template.mMatchRule, merged[0], merged,
-                        CollectionUtils.isEmpty(matchWifiNetworkKeys)
-                                ? null : matchWifiNetworkKeys[0]);
-            }
-        }
-
-        return template;
-    }
-
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
-        @Override
-        public NetworkTemplate createFromParcel(Parcel in) {
-            return new NetworkTemplate(in);
-        }
-
-        @Override
-        public NetworkTemplate[] newArray(int size) {
-            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<>(Comparator.nullsFirst(Comparator.naturalOrder()));
-        @NonNull
-        private final SortedSet<String> mMatchWifiNetworkKeys = new TreeSet<>();
-
-        // 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;
-            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 Keys. Calling this function with an empty set represents
-         * the intention of matching any Wifi Network Key.
-         *
-         * @param wifiNetworkKeys the list of Wifi Network Key,
-         *                        see {@link WifiInfo#getNetworkKey()}.
-         *                        Or an empty list to match all networks.
-         *                        Note that {@code getNetworkKey()} might get null key
-         *                        when wifi disconnects. However, the caller should never invoke
-         *                        this function with a null Wifi Network Key since such statistics
-         *                        never exists.
-         * @return this builder.
-         */
-        @NonNull
-        public Builder setWifiNetworkKeys(@NonNull Set<String> wifiNetworkKeys) {
-            Objects.requireNonNull(wifiNetworkKeys);
-            for (String key : wifiNetworkKeys) {
-                if (key == null) {
-                    throw new IllegalArgumentException("Null is not a valid key");
-                }
-            }
-            mMatchWifiNetworkKeys.clear();
-            mMatchWifiNetworkKeys.addAll(wifiNetworkKeys);
-            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(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() {
-            validateWifiNetworkKeys();
-            // TODO: Check all the input are legitimate.
-        }
-
-        private void validateWifiNetworkKeys() {
-            if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) {
-                throw new IllegalArgumentException("Trying to build non wifi match rule: "
-                        + mMatchRule + " with wifi network keys");
-            }
-        }
-
-        /**
-         * 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()
-                    && mMatchWifiNetworkKeys.isEmpty()) {
-                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()
-                    ? NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL
-                    : NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT;
-            return new NetworkTemplate(getWildcardDeducedMatchRule(),
-                    mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(),
-                    mMatchSubscriberIds.toArray(new String[0]),
-                    mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming,
-                    mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule);
-        }
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
deleted file mode 100644
index bc836d8..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ /dev/null
@@ -1,1148 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.app.DownloadManager;
-import android.app.backup.BackupManager;
-import android.app.usage.NetworkStatsManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.media.MediaPlayer;
-import android.os.Binder;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.StrictMode;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.DatagramSocket;
-import java.net.Socket;
-import java.net.SocketException;
-
-/**
- * Class that provides network traffic statistics. These statistics include
- * bytes transmitted and received and network packets transmitted and received,
- * over all interfaces, over the mobile interface, and on a per-UID basis.
- * <p>
- * These statistics may not be available on all platforms. If the statistics are
- * not supported by this device, {@link #UNSUPPORTED} will be returned.
- * <p>
- * Note that the statistics returned by this class reset and start from zero
- * after every reboot. To access more robust historical network statistics data,
- * use {@link NetworkStatsManager} instead.
- */
-public class TrafficStats {
-    static {
-        System.loadLibrary("framework-connectivity-tiramisu-jni");
-    }
-
-    private static final String TAG = TrafficStats.class.getSimpleName();
-    /**
-     * The return value to indicate that the device does not support the statistic.
-     */
-    public final static int UNSUPPORTED = -1;
-
-    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
-    @Deprecated
-    public static final long KB_IN_BYTES = 1024;
-    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
-    @Deprecated
-    public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
-    @Deprecated
-    public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
-    @Deprecated
-    public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
-    /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */
-    @Deprecated
-    public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;
-
-    /**
-     * Special UID value used when collecting {@link NetworkStatsHistory} for
-     * removed applications.
-     *
-     * @hide
-     */
-    public static final int UID_REMOVED = -4;
-
-    /**
-     * Special UID value used when collecting {@link NetworkStatsHistory} for
-     * tethering traffic.
-     *
-     * @hide
-     */
-    public static final int UID_TETHERING = NetworkStats.UID_TETHERING;
-
-    /**
-     * Tag values in this range are reserved for the network stack. The network stack is
-     * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline
-     * module separate process, and as the system UID otherwise.
-     */
-    /** @hide */
-    @SystemApi
-    public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00;
-    /** @hide */
-    @SystemApi
-    public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF;
-
-    /**
-     * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services
-     * like DownloadManager when performing traffic on behalf of an application.
-     */
-    // Please note there is no enforcement of these constants, so do not rely on them to
-    // determine that the caller is a system caller.
-    /** @hide */
-    @SystemApi
-    public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00;
-    /** @hide */
-    @SystemApi
-    public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F;
-
-    /**
-     * Tag values between these ranges are reserved for the network stack to do traffic
-     * on behalf of applications. It is a subrange of the range above.
-     */
-    /** @hide */
-    @SystemApi
-    public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80;
-    /** @hide */
-    @SystemApi
-    public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F;
-
-    /**
-     * Default tag value for {@link DownloadManager} traffic.
-     *
-     * @hide
-     */
-    public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
-
-    /**
-     * Default tag value for {@link MediaPlayer} traffic.
-     *
-     * @hide
-     */
-    public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
-
-    /**
-     * Default tag value for {@link BackupManager} backup traffic; that is,
-     * traffic from the device to the storage backend.
-     *
-     * @hide
-     */
-    public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
-
-    /**
-     * Default tag value for {@link BackupManager} restore traffic; that is,
-     * app data retrieved from the storage backend at install time.
-     *
-     * @hide
-     */
-    public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04;
-
-    /**
-     * Default tag value for code (typically APKs) downloaded by an app store on
-     * behalf of the app, such as updates.
-     *
-     * @hide
-     */
-    public static final int TAG_SYSTEM_APP = 0xFFFFFF05;
-
-    // TODO : remove this constant when Wifi code is updated
-    /** @hide */
-    public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42;
-
-    private static INetworkStatsService sStatsService;
-
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
-    private synchronized static INetworkStatsService getStatsService() {
-        if (sStatsService == null) {
-            throw new IllegalStateException("TrafficStats not initialized, uid="
-                    + Binder.getCallingUid());
-        }
-        return sStatsService;
-    }
-
-    /**
-     * Snapshot of {@link NetworkStats} when the currently active profiling
-     * session started, or {@code null} if no session active.
-     *
-     * @see #startDataProfiling(Context)
-     * @see #stopDataProfiling(Context)
-     */
-    private static NetworkStats sActiveProfilingStart;
-
-    private static Object sProfilingLock = new Object();
-
-    private static final String LOOPBACK_IFACE = "lo";
-
-    /**
-     * Initialization {@link TrafficStats} with the context, to
-     * allow {@link TrafficStats} to fetch the needed binder.
-     *
-     * @param context a long-lived context, such as the application context or system
-     *                server context.
-     * @hide
-     */
-    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-    @SuppressLint("VisiblySynchronized")
-    public static synchronized void init(@NonNull final Context context) {
-        if (sStatsService != null) {
-            throw new IllegalStateException("TrafficStats is already initialized, uid="
-                    + Binder.getCallingUid());
-        }
-        final NetworkStatsManager statsManager =
-                context.getSystemService(NetworkStatsManager.class);
-        if (statsManager == null) {
-            // TODO: Currently Process.isSupplemental is not working yet, because it depends on
-            //  process to run in a certain UID range, which is not true for now. Change this
-            //  to Log.wtf once Process.isSupplemental is ready.
-            Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid());
-            return;
-        }
-        sStatsService = statsManager.getBinder();
-    }
-
-    /**
-     * Attach the socket tagger implementation to the current process, to
-     * get notified when a socket's {@link FileDescriptor} is assigned to
-     * a thread. See {@link SocketTagger#set(SocketTagger)}.
-     *
-     * @hide
-     */
-    @SystemApi(client = MODULE_LIBRARIES)
-    public static void attachSocketTagger() {
-        dalvik.system.SocketTagger.set(new SocketTagger());
-    }
-
-    private static class SocketTagger extends dalvik.system.SocketTagger {
-
-        // TODO: set to false
-        private static final boolean LOGD = true;
-
-        SocketTagger() {
-        }
-
-        @Override
-        public void tag(FileDescriptor fd) throws SocketException {
-            final UidTag tagInfo = sThreadUidTag.get();
-            if (LOGD) {
-                Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
-                        + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
-            }
-            if (tagInfo.tag == -1) {
-                StrictMode.noteUntaggedSocket();
-            }
-
-            if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
-            final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
-            if (errno < 0) {
-                Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
-                        + tagInfo.tag + ", "
-                        + tagInfo.uid + ") failed with errno" + errno);
-            }
-        }
-
-        @Override
-        public void untag(FileDescriptor fd) throws SocketException {
-            if (LOGD) {
-                Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
-            }
-
-            final UidTag tagInfo = sThreadUidTag.get();
-            if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
-
-            final int errno = native_untagSocketFd(fd);
-            if (errno < 0) {
-                Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
-            }
-        }
-    }
-
-    private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
-    private static native int native_untagSocketFd(FileDescriptor fd);
-
-    private static class UidTag {
-        public int tag = -1;
-        public int uid = -1;
-    }
-
-    private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
-        @Override
-        protected UidTag initialValue() {
-            return new UidTag();
-        }
-    };
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. Only one active tag per thread is supported.
-     * <p>
-     * Changes only take effect during subsequent calls to
-     * {@link #tagSocket(Socket)}.
-     * <p>
-     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
-     * used internally by system services like {@link DownloadManager} when
-     * performing traffic on behalf of an application.
-     *
-     * @see #clearThreadStatsTag()
-     */
-    public static void setThreadStatsTag(int tag) {
-        getAndSetThreadStatsTag(tag);
-    }
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. Only one active tag per thread is supported.
-     * <p>
-     * Changes only take effect during subsequent calls to
-     * {@link #tagSocket(Socket)}.
-     * <p>
-     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
-     * used internally by system services like {@link DownloadManager} when
-     * performing traffic on behalf of an application.
-     *
-     * @return the current tag for the calling thread, which can be used to
-     *         restore any existing values after a nested operation is finished
-     */
-    public static int getAndSetThreadStatsTag(int tag) {
-        final int old = sThreadUidTag.get().tag;
-        sThreadUidTag.get().tag = tag;
-        return old;
-    }
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. The tag used internally is well-defined to
-     * distinguish all backup-related traffic.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static void setThreadStatsTagBackup() {
-        setThreadStatsTag(TAG_SYSTEM_BACKUP);
-    }
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. The tag used internally is well-defined to
-     * distinguish all restore-related traffic.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static void setThreadStatsTagRestore() {
-        setThreadStatsTag(TAG_SYSTEM_RESTORE);
-    }
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. The tag used internally is well-defined to
-     * distinguish all code (typically APKs) downloaded by an app store on
-     * behalf of the app, such as updates.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static void setThreadStatsTagApp() {
-        setThreadStatsTag(TAG_SYSTEM_APP);
-    }
-
-    /**
-     * Set active tag to use when accounting {@link Socket} traffic originating
-     * from the current thread. The tag used internally is well-defined to
-     * distinguish all download provider traffic.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static void setThreadStatsTagDownload() {
-        setThreadStatsTag(TAG_SYSTEM_DOWNLOAD);
-    }
-
-    /**
-     * Get the active tag used when accounting {@link Socket} traffic originating
-     * from the current thread. Only one active tag per thread is supported.
-     * {@link #tagSocket(Socket)}.
-     *
-     * @see #setThreadStatsTag(int)
-     */
-    public static int getThreadStatsTag() {
-        return sThreadUidTag.get().tag;
-    }
-
-    /**
-     * Clear any active tag set to account {@link Socket} traffic originating
-     * from the current thread.
-     *
-     * @see #setThreadStatsTag(int)
-     */
-    public static void clearThreadStatsTag() {
-        sThreadUidTag.get().tag = -1;
-    }
-
-    /**
-     * Set specific UID to use when accounting {@link Socket} traffic
-     * originating from the current thread. Designed for use when performing an
-     * operation on behalf of another application, or when another application
-     * is performing operations on your behalf.
-     * <p>
-     * Any app can <em>accept</em> blame for traffic performed on a socket
-     * originally created by another app by calling this method with the
-     * {@link android.system.Os#getuid()} value. However, only apps holding the
-     * {@code android.Manifest.permission#UPDATE_DEVICE_STATS} permission may
-     * <em>assign</em> blame to another UIDs.
-     * <p>
-     * Changes only take effect during subsequent calls to
-     * {@link #tagSocket(Socket)}.
-     */
-    @SuppressLint("RequiresPermission")
-    public static void setThreadStatsUid(int uid) {
-        sThreadUidTag.get().uid = uid;
-    }
-
-    /**
-     * Get the active UID used when accounting {@link Socket} traffic originating
-     * from the current thread. Only one active tag per thread is supported.
-     * {@link #tagSocket(Socket)}.
-     *
-     * @see #setThreadStatsUid(int)
-     */
-    public static int getThreadStatsUid() {
-        return sThreadUidTag.get().uid;
-    }
-
-    /**
-     * Set specific UID to use when accounting {@link Socket} traffic
-     * originating from the current thread as the calling UID. Designed for use
-     * when another application is performing operations on your behalf.
-     * <p>
-     * Changes only take effect during subsequent calls to
-     * {@link #tagSocket(Socket)}.
-     *
-     * @removed
-     * @deprecated use {@link #setThreadStatsUid(int)} instead.
-     */
-    @Deprecated
-    public static void setThreadStatsUidSelf() {
-        setThreadStatsUid(android.os.Process.myUid());
-    }
-
-    /**
-     * Clear any active UID set to account {@link Socket} traffic originating
-     * from the current thread.
-     *
-     * @see #setThreadStatsUid(int)
-     */
-    @SuppressLint("RequiresPermission")
-    public static void clearThreadStatsUid() {
-        setThreadStatsUid(-1);
-    }
-
-    /**
-     * Tag the given {@link Socket} with any statistics parameters active for
-     * the current thread. Subsequent calls always replace any existing
-     * parameters. When finished, call {@link #untagSocket(Socket)} to remove
-     * statistics parameters.
-     *
-     * @see #setThreadStatsTag(int)
-     */
-    public static void tagSocket(Socket socket) throws SocketException {
-        SocketTagger.get().tag(socket);
-    }
-
-    /**
-     * Remove any statistics parameters from the given {@link Socket}.
-     * <p>
-     * In Android 8.1 (API level 27) and lower, a socket is automatically
-     * untagged when it's sent to another process using binder IPC with a
-     * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28)
-     * and higher, the socket tag is kept when the socket is sent to another
-     * process using binder IPC. You can mimic the previous behavior by
-     * calling {@code untagSocket()} before sending the socket to another
-     * process.
-     */
-    public static void untagSocket(Socket socket) throws SocketException {
-        SocketTagger.get().untag(socket);
-    }
-
-    /**
-     * Tag the given {@link DatagramSocket} with any statistics parameters
-     * active for the current thread. Subsequent calls always replace any
-     * existing parameters. When finished, call
-     * {@link #untagDatagramSocket(DatagramSocket)} to remove statistics
-     * parameters.
-     *
-     * @see #setThreadStatsTag(int)
-     */
-    public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
-        SocketTagger.get().tag(socket);
-    }
-
-    /**
-     * Remove any statistics parameters from the given {@link DatagramSocket}.
-     */
-    public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
-        SocketTagger.get().untag(socket);
-    }
-
-    /**
-     * Tag the given {@link FileDescriptor} socket with any statistics
-     * parameters active for the current thread. Subsequent calls always replace
-     * any existing parameters. When finished, call
-     * {@link #untagFileDescriptor(FileDescriptor)} to remove statistics
-     * parameters.
-     *
-     * @see #setThreadStatsTag(int)
-     */
-    public static void tagFileDescriptor(FileDescriptor fd) throws IOException {
-        SocketTagger.get().tag(fd);
-    }
-
-    /**
-     * Remove any statistics parameters from the given {@link FileDescriptor}
-     * socket.
-     */
-    public static void untagFileDescriptor(FileDescriptor fd) throws IOException {
-        SocketTagger.get().untag(fd);
-    }
-
-    /**
-     * Start profiling data usage for current UID. Only one profiling session
-     * can be active at a time.
-     *
-     * @hide
-     */
-    public static void startDataProfiling(Context context) {
-        synchronized (sProfilingLock) {
-            if (sActiveProfilingStart != null) {
-                throw new IllegalStateException("already profiling data");
-            }
-
-            // take snapshot in time; we calculate delta later
-            sActiveProfilingStart = getDataLayerSnapshotForUid(context);
-        }
-    }
-
-    /**
-     * Stop profiling data usage for current UID.
-     *
-     * @return Detailed {@link NetworkStats} of data that occurred since last
-     *         {@link #startDataProfiling(Context)} call.
-     * @hide
-     */
-    public static NetworkStats stopDataProfiling(Context context) {
-        synchronized (sProfilingLock) {
-            if (sActiveProfilingStart == null) {
-                throw new IllegalStateException("not profiling data");
-            }
-
-            // subtract starting values and return delta
-            final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
-            final NetworkStats profilingDelta = NetworkStats.subtract(
-                    profilingStop, sActiveProfilingStart, null, null);
-            sActiveProfilingStart = null;
-            return profilingDelta;
-        }
-    }
-
-    /**
-     * Increment count of network operations performed under the accounting tag
-     * currently active on the calling thread. This can be used to derive
-     * bytes-per-operation.
-     *
-     * @param operationCount Number of operations to increment count by.
-     */
-    public static void incrementOperationCount(int operationCount) {
-        final int tag = getThreadStatsTag();
-        incrementOperationCount(tag, operationCount);
-    }
-
-    /**
-     * Increment count of network operations performed under the given
-     * accounting tag. This can be used to derive bytes-per-operation.
-     *
-     * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
-     * @param operationCount Number of operations to increment count by.
-     */
-    public static void incrementOperationCount(int tag, int operationCount) {
-        final int uid = android.os.Process.myUid();
-        try {
-            getStatsService().incrementOperationCount(uid, tag, operationCount);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    public static void closeQuietly(INetworkStatsSession session) {
-        // TODO: move to NetworkStatsService once it exists
-        if (session != null) {
-            try {
-                session.close();
-            } catch (RuntimeException rethrown) {
-                throw rethrown;
-            } catch (Exception ignored) {
-            }
-        }
-    }
-
-    private static long addIfSupported(long stat) {
-        return (stat == UNSUPPORTED) ? 0 : stat;
-    }
-
-    /**
-     * Return number of packets transmitted across mobile networks since device
-     * boot. Counts packets across all mobile network interfaces, and always
-     * increases monotonically since device boot. Statistics are measured at the
-     * network layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getMobileTxPackets() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            total += addIfSupported(getTxPackets(iface));
-        }
-        return total;
-    }
-
-    /**
-     * Return number of packets received across mobile networks since device
-     * boot. Counts packets across all mobile network interfaces, and always
-     * increases monotonically since device boot. Statistics are measured at the
-     * network layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getMobileRxPackets() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            total += addIfSupported(getRxPackets(iface));
-        }
-        return total;
-    }
-
-    /**
-     * Return number of bytes transmitted across mobile networks since device
-     * boot. Counts packets across all mobile network interfaces, and always
-     * increases monotonically since device boot. Statistics are measured at the
-     * network layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getMobileTxBytes() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            total += addIfSupported(getTxBytes(iface));
-        }
-        return total;
-    }
-
-    /**
-     * Return number of bytes received across mobile networks since device boot.
-     * Counts packets across all mobile network interfaces, and always increases
-     * monotonically since device boot. Statistics are measured at the network
-     * layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getMobileRxBytes() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            total += addIfSupported(getRxBytes(iface));
-        }
-        return total;
-    }
-
-    /** {@hide} */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static long getMobileTcpRxPackets() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            long stat = UNSUPPORTED;
-            try {
-                stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            total += addIfSupported(stat);
-        }
-        return total;
-    }
-
-    /** {@hide} */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static long getMobileTcpTxPackets() {
-        long total = 0;
-        for (String iface : getMobileIfaces()) {
-            long stat = UNSUPPORTED;
-            try {
-                stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-            total += addIfSupported(stat);
-        }
-        return total;
-    }
-
-    /**
-     * Return the number of packets transmitted on the specified interface since the interface
-     * was created. Statistics are measured at the network layer, so both TCP and
-     * UDP usage are included.
-     *
-     * Note that the returned values are partial statistics that do not count data from several
-     * sources and do not apply several adjustments that are necessary for correctness, such
-     * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
-     * determine whether traffic is being transferred on the specific interface but are not a
-     * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
-     * APIs.
-     *
-     * @param iface The name of the interface.
-     * @return The number of transmitted packets.
-     */
-    public static long getTxPackets(@NonNull String iface) {
-        try {
-            return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return the number of packets received on the specified interface since the interface was
-     * created. Statistics are measured at the network layer, so both TCP
-     * and UDP usage are included.
-     *
-     * Note that the returned values are partial statistics that do not count data from several
-     * sources and do not apply several adjustments that are necessary for correctness, such
-     * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
-     * determine whether traffic is being transferred on the specific interface but are not a
-     * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
-     * APIs.
-     *
-     * @param iface The name of the interface.
-     * @return The number of received packets.
-     */
-    public static long getRxPackets(@NonNull String iface) {
-        try {
-            return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return the number of bytes transmitted on the specified interface since the interface
-     * was created. Statistics are measured at the network layer, so both TCP and
-     * UDP usage are included.
-     *
-     * Note that the returned values are partial statistics that do not count data from several
-     * sources and do not apply several adjustments that are necessary for correctness, such
-     * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
-     * determine whether traffic is being transferred on the specific interface but are not a
-     * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
-     * APIs.
-     *
-     * @param iface The name of the interface.
-     * @return The number of transmitted bytes.
-     */
-    public static long getTxBytes(@NonNull String iface) {
-        try {
-            return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return the number of bytes received on the specified interface since the interface
-     * was created. Statistics are measured at the network layer, so both TCP
-     * and UDP usage are included.
-     *
-     * Note that the returned values are partial statistics that do not count data from several
-     * sources and do not apply several adjustments that are necessary for correctness, such
-     * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to
-     * determine whether traffic is being transferred on the specific interface but are not a
-     * substitute for the more accurate statistics provided by the {@link NetworkStatsManager}
-     * APIs.
-     *
-     * @param iface The name of the interface.
-     * @return The number of received bytes.
-     */
-    public static long getRxBytes(@NonNull String iface) {
-        try {
-            return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    @TestApi
-    public static long getLoopbackTxPackets() {
-        try {
-            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    @TestApi
-    public static long getLoopbackRxPackets() {
-        try {
-            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    @TestApi
-    public static long getLoopbackTxBytes() {
-        try {
-            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    @TestApi
-    public static long getLoopbackRxBytes() {
-        try {
-            return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of packets transmitted since device boot. Counts packets
-     * across all network interfaces, and always increases monotonically since
-     * device boot. Statistics are measured at the network layer, so they
-     * include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getTotalTxPackets() {
-        try {
-            return getStatsService().getTotalStats(TYPE_TX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of packets received since device boot. Counts packets
-     * across all network interfaces, and always increases monotonically since
-     * device boot. Statistics are measured at the network layer, so they
-     * include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getTotalRxPackets() {
-        try {
-            return getStatsService().getTotalStats(TYPE_RX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of bytes transmitted since device boot. Counts packets
-     * across all network interfaces, and always increases monotonically since
-     * device boot. Statistics are measured at the network layer, so they
-     * include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getTotalTxBytes() {
-        try {
-            return getStatsService().getTotalStats(TYPE_TX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of bytes received since device boot. Counts packets across
-     * all network interfaces, and always increases monotonically since device
-     * boot. Statistics are measured at the network layer, so they include both
-     * TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     */
-    public static long getTotalRxBytes() {
-        try {
-            return getStatsService().getTotalStats(TYPE_RX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of bytes transmitted by the given UID since device boot.
-     * Counts packets across all network interfaces, and always increases
-     * monotonically since device boot. Statistics are measured at the network
-     * layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
-     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
-     * <p>
-     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
-     * report traffic statistics for the calling UID. It will return
-     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
-     * historical network statistics belonging to other UIDs, use
-     * {@link NetworkStatsManager}.
-     *
-     * @see android.os.Process#myUid()
-     * @see android.content.pm.ApplicationInfo#uid
-     */
-    public static long getUidTxBytes(int uid) {
-        try {
-            return getStatsService().getUidStats(uid, TYPE_TX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of bytes received by the given UID since device boot.
-     * Counts packets across all network interfaces, and always increases
-     * monotonically since device boot. Statistics are measured at the network
-     * layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
-     * {@link #UNSUPPORTED} on devices where statistics aren't available.
-     * <p>
-     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
-     * report traffic statistics for the calling UID. It will return
-     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
-     * historical network statistics belonging to other UIDs, use
-     * {@link NetworkStatsManager}.
-     *
-     * @see android.os.Process#myUid()
-     * @see android.content.pm.ApplicationInfo#uid
-     */
-    public static long getUidRxBytes(int uid) {
-        try {
-            return getStatsService().getUidStats(uid, TYPE_RX_BYTES);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of packets transmitted by the given UID since device boot.
-     * Counts packets across all network interfaces, and always increases
-     * monotonically since device boot. Statistics are measured at the network
-     * layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
-     * {@link #UNSUPPORTED} on devices where statistics aren't available.
-     * <p>
-     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
-     * report traffic statistics for the calling UID. It will return
-     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
-     * historical network statistics belonging to other UIDs, use
-     * {@link NetworkStatsManager}.
-     *
-     * @see android.os.Process#myUid()
-     * @see android.content.pm.ApplicationInfo#uid
-     */
-    public static long getUidTxPackets(int uid) {
-        try {
-            return getStatsService().getUidStats(uid, TYPE_TX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return number of packets received by the given UID since device boot.
-     * Counts packets across all network interfaces, and always increases
-     * monotonically since device boot. Statistics are measured at the network
-     * layer, so they include both TCP and UDP usage.
-     * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
-     * {@link #UNSUPPORTED} on devices where statistics aren't available.
-     * <p>
-     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
-     * report traffic statistics for the calling UID. It will return
-     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
-     * historical network statistics belonging to other UIDs, use
-     * {@link NetworkStatsManager}.
-     *
-     * @see android.os.Process#myUid()
-     * @see android.content.pm.ApplicationInfo#uid
-     */
-    public static long getUidRxPackets(int uid) {
-        try {
-            return getStatsService().getUidStats(uid, TYPE_RX_PACKETS);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidTxBytes(int)
-     */
-    @Deprecated
-    public static long getUidTcpTxBytes(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidRxBytes(int)
-     */
-    @Deprecated
-    public static long getUidTcpRxBytes(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidTxBytes(int)
-     */
-    @Deprecated
-    public static long getUidUdpTxBytes(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidRxBytes(int)
-     */
-    @Deprecated
-    public static long getUidUdpRxBytes(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidTxPackets(int)
-     */
-    @Deprecated
-    public static long getUidTcpTxSegments(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidRxPackets(int)
-     */
-    @Deprecated
-    public static long getUidTcpRxSegments(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidTxPackets(int)
-     */
-    @Deprecated
-    public static long getUidUdpTxPackets(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * @deprecated Starting in {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
-     *             transport layer statistics are no longer available, and will
-     *             always return {@link #UNSUPPORTED}.
-     * @see #getUidRxPackets(int)
-     */
-    @Deprecated
-    public static long getUidUdpRxPackets(int uid) {
-        return UNSUPPORTED;
-    }
-
-    /**
-     * Return detailed {@link NetworkStats} for the current UID. Requires no
-     * special permission.
-     */
-    private static NetworkStats getDataLayerSnapshotForUid(Context context) {
-        // TODO: take snapshot locally, since proc file is now visible
-        final int uid = android.os.Process.myUid();
-        try {
-            return getStatsService().getDataLayerSnapshotForUid(uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return set of any ifaces associated with mobile networks since boot.
-     * Interfaces are never removed from this list, so counters should always be
-     * monotonic.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
-    private static String[] getMobileIfaces() {
-        try {
-            return getStatsService().getMobileIfaces();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}.
-    /** {@hide} */
-    public static final int TYPE_RX_BYTES = 0;
-    /** {@hide} */
-    public static final int TYPE_RX_PACKETS = 1;
-    /** {@hide} */
-    public static final int TYPE_TX_BYTES = 2;
-    /** {@hide} */
-    public static final int TYPE_TX_PACKETS = 3;
-    /** {@hide} */
-    public static final int TYPE_TCP_RX_PACKETS = 4;
-    /** {@hide} */
-    public static final int TYPE_TCP_TX_PACKETS = 5;
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl
deleted file mode 100644
index a56f2f4..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-parcelable UnderlyingNetworkInfo;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
deleted file mode 100644
index 33f9375..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A lightweight container used to carry information on the networks that underly a given
- * virtual network.
- *
- * @hide
- */
-@SystemApi(client = MODULE_LIBRARIES)
-public final class UnderlyingNetworkInfo implements Parcelable {
-    /** The owner of this network. */
-    private final int mOwnerUid;
-
-    /** The interface name of this network. */
-    @NonNull
-    private final String mIface;
-
-    /** The names of the interfaces underlying this network. */
-    @NonNull
-    private final List<String> mUnderlyingIfaces;
-
-    public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface,
-            @NonNull List<String> underlyingIfaces) {
-        Objects.requireNonNull(iface);
-        Objects.requireNonNull(underlyingIfaces);
-        mOwnerUid = ownerUid;
-        mIface = iface;
-        mUnderlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces));
-    }
-
-    private UnderlyingNetworkInfo(@NonNull Parcel in) {
-        mOwnerUid = in.readInt();
-        mIface = in.readString();
-        List<String> underlyingIfaces = new ArrayList<>();
-        in.readList(underlyingIfaces, null /*classLoader*/);
-        mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces);
-    }
-
-    /** Get the owner of this network. */
-    public int getOwnerUid() {
-        return mOwnerUid;
-    }
-
-    /** Get the interface name of this network. */
-    @NonNull
-    public String getInterface() {
-        return mIface;
-    }
-
-    /** Get the names of the interfaces underlying this network. */
-    @NonNull
-    public List<String> getUnderlyingInterfaces() {
-        return mUnderlyingIfaces;
-    }
-
-    @Override
-    public String toString() {
-        return "UnderlyingNetworkInfo{"
-                + "ownerUid=" + mOwnerUid
-                + ", iface='" + mIface + '\''
-                + ", underlyingIfaces='" + mUnderlyingIfaces.toString() + '\''
-                + '}';
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mOwnerUid);
-        dest.writeString(mIface);
-        dest.writeList(mUnderlyingIfaces);
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<UnderlyingNetworkInfo> CREATOR =
-            new Parcelable.Creator<UnderlyingNetworkInfo>() {
-        @NonNull
-        @Override
-        public UnderlyingNetworkInfo createFromParcel(@NonNull Parcel in) {
-            return new UnderlyingNetworkInfo(in);
-        }
-
-        @NonNull
-        @Override
-        public UnderlyingNetworkInfo[] newArray(int size) {
-            return new UnderlyingNetworkInfo[size];
-        }
-    };
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof UnderlyingNetworkInfo)) return false;
-        final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
-        return mOwnerUid == that.getOwnerUid()
-                && Objects.equals(mIface, that.getInterface())
-                && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces());
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mOwnerUid, mIface, mUnderlyingIfaces);
-    }
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
deleted file mode 100644
index 4e8a5b2..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.netstats;
-
-import android.net.DataUsageRequest;
-
-/**
- * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback.
- *
- * @hide
- */
-oneway interface IUsageCallback {
-    void onThresholdReached(in DataUsageRequest request);
-    void onCallbackReleased(in DataUsageRequest request);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
deleted file mode 100644
index 74c3ba4..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netstats.provider;
-
-/**
- * Interface for NetworkStatsService to query network statistics and set data limits.
- *
- * @hide
- */
-oneway interface INetworkStatsProvider {
-    void onRequestStatsUpdate(int token);
-    void onSetAlert(long quotaBytes);
-    void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
deleted file mode 100644
index 01ff02d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netstats.provider;
-
-import android.net.NetworkStats;
-
-/**
- * Interface for implementor of {@link INetworkStatsProviderCallback} to push events
- * such as network statistics update or notify limit reached.
- * @hide
- */
-oneway interface INetworkStatsProviderCallback {
-    void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
-    void notifyAlertReached();
-    void notifyWarningReached();
-    void notifyLimitReached();
-    void unregister();
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
deleted file mode 100644
index d37a53d..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.netstats.provider;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.net.NetworkStats;
-import android.os.RemoteException;
-
-/**
- * A base class that allows external modules to implement a custom network statistics provider.
- * @hide
- */
-@SystemApi
-public abstract class NetworkStatsProvider {
-    /**
-     * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit}
-     * indicates there is no limit.
-     */
-    public static final int QUOTA_UNLIMITED = -1;
-
-    @NonNull private final INetworkStatsProvider mProviderBinder =
-            new INetworkStatsProvider.Stub() {
-
-        @Override
-        public void onRequestStatsUpdate(int token) {
-            NetworkStatsProvider.this.onRequestStatsUpdate(token);
-        }
-
-        @Override
-        public void onSetAlert(long quotaBytes) {
-            NetworkStatsProvider.this.onSetAlert(quotaBytes);
-        }
-
-        @Override
-        public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) {
-            NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes);
-        }
-    };
-
-    // The binder given by the service when successfully registering. Only null before registering,
-    // never null once non-null.
-    @Nullable
-    private INetworkStatsProviderCallback mProviderCbBinder;
-
-    /**
-     * Return the binder invoked by the service and redirect function calls to the overridden
-     * methods.
-     * @hide
-     */
-    @NonNull
-    public INetworkStatsProvider getProviderBinder() {
-        return mProviderBinder;
-    }
-
-    /**
-     * Store the binder that was returned by the service when successfully registering. Note that
-     * the provider cannot be re-registered. Hence this method can only be called once per provider.
-     *
-     * @hide
-     */
-    public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) {
-        if (mProviderCbBinder != null) {
-            throw new IllegalArgumentException("provider is already registered");
-        }
-        mProviderCbBinder = binder;
-    }
-
-    /**
-     * Get the binder that was returned by the service when successfully registering. Or null if the
-     * provider was never registered.
-     *
-     * @hide
-     */
-    @Nullable
-    public INetworkStatsProviderCallback getProviderCallbackBinder() {
-        return mProviderCbBinder;
-    }
-
-    /**
-     * Get the binder that was returned by the service when successfully registering. Throw an
-     * {@link IllegalStateException} if the provider is not registered.
-     *
-     * @hide
-     */
-    @NonNull
-    public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() {
-        if (mProviderCbBinder == null) {
-            throw new IllegalStateException("the provider is not registered");
-        }
-        return mProviderCbBinder;
-    }
-
-    /**
-     * Notify the system of new network statistics.
-     *
-     * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must
-     * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)}
-     * being called. Responding later increases the probability stats will be dropped. The
-     * provider can also call this whenever it wants to reports new stats for any reason.
-     * Note that the system will not necessarily immediately propagate the statistics to
-     * reflect the update.
-     *
-     * @param token the token under which these stats were gathered. Providers can call this method
-     *              with the current token as often as they want, until the token changes.
-     *              {@see NetworkStatsProvider#onRequestStatsUpdate()}
-     * @param ifaceStats the {@link NetworkStats} per interface to be reported.
-     *                   The provider should not include any traffic that is already counted by
-     *                   kernel interface counters.
-     * @param uidStats the same stats as above, but counts {@link NetworkStats}
-     *                 per uid.
-     */
-    public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
-            @NonNull NetworkStats uidStats) {
-        try {
-            getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Notify system that the quota set by {@code onSetAlert} has been reached.
-     */
-    public void notifyAlertReached() {
-        try {
-            getProviderCallbackBinderOrThrow().notifyAlertReached();
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached.
-     */
-    public void notifyWarningReached() {
-        try {
-            // Reuse the code path to notify warning reached with limit reached
-            // since framework handles them in the same way.
-            getProviderCallbackBinderOrThrow().notifyWarningReached();
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Notify system that the limit set by {@link #onSetLimit} or limit set by
-     * {@link #onSetWarningAndLimit} has been reached.
-     */
-    public void notifyLimitReached() {
-        try {
-            getProviderCallbackBinderOrThrow().notifyLimitReached();
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    /**
-     * Called by {@code NetworkStatsService} when it requires to know updated stats.
-     * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible.
-     * Responding later increases the probability stats will be dropped. Memory allowing, the
-     * system will try to take stats into account up to one minute after calling
-     * {@link #onRequestStatsUpdate}.
-     *
-     * @param token a positive number identifying the new state of the system under which
-     *              {@link NetworkStats} have to be gathered from now on. When this is called,
-     *              custom implementations of providers MUST tally and report the latest stats with
-     *              the previous token, under which stats were being gathered so far.
-     */
-    public abstract void onRequestStatsUpdate(int token);
-
-    /**
-     * Called by {@code NetworkStatsService} when setting the interface quota for the specified
-     * upstream interface. When this is called, the custom implementation should block all egress
-     * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
-     * been reached, and MUST respond to it by calling
-     * {@link NetworkStatsProvider#notifyLimitReached()}.
-     *
-     * @param iface the interface requiring the operation.
-     * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
-     *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
-     */
-    public abstract void onSetLimit(@NonNull String iface, long quotaBytes);
-
-    /**
-     * Called by {@code NetworkStatsService} when setting the interface quotas for the specified
-     * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system
-     * will not call {@link #onSetLimit}. When this method is called, the implementation
-     * should behave as follows:
-     *   1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on
-     *      {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}.
-     *   2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on
-     *   {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}.
-     *
-     * @param iface the interface requiring the operation.
-     * @param warningBytes the warning defined as the number of bytes, starting from zero and
-     *                     counting from now. A value of {@link #QUOTA_UNLIMITED} indicates
-     *                     there is no warning.
-     * @param limitBytes the limit defined as the number of bytes, starting from zero and counting
-     *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
-     */
-    public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) {
-        // Backward compatibility for those who didn't override this function.
-        onSetLimit(iface, limitBytes);
-    }
-
-    /**
-     * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
-     * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes
-     * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should
-     * not block all egress packets.
-     *
-     * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
-     *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
-     */
-    public abstract void onSetAlert(long quotaBytes);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
deleted file mode 100644
index 89e9cdb..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.nsd;
-
-import android.net.nsd.INsdManagerCallback;
-import android.net.nsd.INsdServiceConnector;
-import android.os.Messenger;
-
-/**
- * Interface that NsdService implements to connect NsdManager clients.
- *
- * {@hide}
- */
-interface INsdManager {
-    INsdServiceConnector connect(INsdManagerCallback cb);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
deleted file mode 100644
index 1a262ec..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.nsd;
-
-import android.os.Messenger;
-import android.net.nsd.NsdServiceInfo;
-
-/**
- * Callbacks from NsdService to NsdManager
- * @hide
- */
-oneway interface INsdManagerCallback {
-    void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info);
-    void onDiscoverServicesFailed(int listenerKey, int error);
-    void onServiceFound(int listenerKey, in NsdServiceInfo info);
-    void onServiceLost(int listenerKey, in NsdServiceInfo info);
-    void onStopDiscoveryFailed(int listenerKey, int error);
-    void onStopDiscoverySucceeded(int listenerKey);
-    void onRegisterServiceFailed(int listenerKey, int error);
-    void onRegisterServiceSucceeded(int listenerKey, in NsdServiceInfo info);
-    void onUnregisterServiceFailed(int listenerKey, int error);
-    void onUnregisterServiceSucceeded(int listenerKey);
-    void onResolveServiceFailed(int listenerKey, int error);
-    void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info);
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
deleted file mode 100644
index b06ae55..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.nsd;
-
-import android.net.nsd.INsdManagerCallback;
-import android.net.nsd.NsdServiceInfo;
-import android.os.Messenger;
-
-/**
- * Interface that NsdService implements for each NsdManager client.
- *
- * {@hide}
- */
-interface INsdServiceConnector {
-    void registerService(int listenerKey, in NsdServiceInfo serviceInfo);
-    void unregisterService(int listenerKey);
-    void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo);
-    void stopDiscovery(int listenerKey);
-    void resolveService(int listenerKey, in NsdServiceInfo serviceInfo);
-    void startDaemon();
-}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
deleted file mode 100644
index 209f372..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.nsd;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemService;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.net.NetworkRequest;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * The Network Service Discovery Manager class provides the API to discover services
- * on a network. As an example, if device A and device B are connected over a Wi-Fi
- * network, a game registered on device A can be discovered by a game on device
- * B. Another example use case is an application discovering printers on the network.
- *
- * <p> The API currently supports DNS based service discovery and discovery is currently
- * limited to a local network over Multicast DNS. DNS service discovery is described at
- * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
- *
- * <p> The API is asynchronous, and responses to requests from an application are on listener
- * callbacks on a separate internal thread.
- *
- * <p> There are three main operations the API supports - registration, discovery and resolution.
- * <pre>
- *                          Application start
- *                                 |
- *                                 |
- *                                 |                  onServiceRegistered()
- *                     Register any local services  /
- *                      to be advertised with       \
- *                       registerService()            onRegistrationFailed()
- *                                 |
- *                                 |
- *                          discoverServices()
- *                                 |
- *                      Maintain a list to track
- *                        discovered services
- *                                 |
- *                                 |--------->
- *                                 |          |
- *                                 |      onServiceFound()
- *                                 |          |
- *                                 |     add service to list
- *                                 |          |
- *                                 |<----------
- *                                 |
- *                                 |--------->
- *                                 |          |
- *                                 |      onServiceLost()
- *                                 |          |
- *                                 |   remove service from list
- *                                 |          |
- *                                 |<----------
- *                                 |
- *                                 |
- *                                 | Connect to a service
- *                                 | from list ?
- *                                 |
- *                          resolveService()
- *                                 |
- *                         onServiceResolved()
- *                                 |
- *                     Establish connection to service
- *                     with the host and port information
- *
- * </pre>
- * An application that needs to advertise itself over a network for other applications to
- * discover it can do so with a call to {@link #registerService}. If Example is a http based
- * application that can provide HTML data to peer services, it can register a name "Example"
- * with service type "_http._tcp". A successful registration is notified with a callback to
- * {@link RegistrationListener#onServiceRegistered} and a failure to register is notified
- * over {@link RegistrationListener#onRegistrationFailed}
- *
- * <p> A peer application looking for http services can initiate a discovery for "_http._tcp"
- * with a call to {@link #discoverServices}. A service found is notified with a callback
- * to {@link DiscoveryListener#onServiceFound} and a service lost is notified on
- * {@link DiscoveryListener#onServiceLost}.
- *
- * <p> Once the peer application discovers the "Example" http service, and either needs to read the
- * attributes of the service or wants to receive data from the "Example" application, it can
- * initiate a resolve with {@link #resolveService} to resolve the attributes, host, and port
- * details. A successful resolve is notified on {@link ResolveListener#onServiceResolved} and a
- * failure is notified on {@link ResolveListener#onResolveFailed}.
- *
- * Applications can reserve for a service type at
- * http://www.iana.org/form/ports-service. Existing services can be found at
- * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
- *
- * {@see NsdServiceInfo}
- */
-@SystemService(Context.NSD_SERVICE)
-public final class NsdManager {
-    private static final String TAG = NsdManager.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    /**
-     * When enabled, apps targeting < Android 12 are considered legacy for
-     * the NSD native daemon.
-     * The platform will only keep the daemon running as long as there are
-     * any legacy apps connected.
-     *
-     * After Android 12, directly communicate with native daemon might not
-     * work since the native damon won't always stay alive.
-     * Use the NSD APIs from NsdManager as the replacement is recommended.
-     * An another alternative could be bundling your own mdns solutions instead of
-     * depending on the system mdns native daemon.
-     *
-     * @hide
-     */
-    @ChangeId
-    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
-    public static final long RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS = 191844585L;
-
-    /**
-     * Broadcast intent action to indicate whether network service discovery is
-     * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
-     * information as int.
-     *
-     * @see #EXTRA_NSD_STATE
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
-
-    /**
-     * The lookup key for an int that indicates whether network service discovery is enabled
-     * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
-     *
-     * @see #NSD_STATE_DISABLED
-     * @see #NSD_STATE_ENABLED
-     */
-    public static final String EXTRA_NSD_STATE = "nsd_state";
-
-    /**
-     * Network service discovery is disabled
-     *
-     * @see #ACTION_NSD_STATE_CHANGED
-     */
-    public static final int NSD_STATE_DISABLED = 1;
-
-    /**
-     * Network service discovery is enabled
-     *
-     * @see #ACTION_NSD_STATE_CHANGED
-     */
-    public static final int NSD_STATE_ENABLED = 2;
-
-    /** @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 STOP_DISCOVERY                          = 6;
-    /** @hide */
-    public static final int STOP_DISCOVERY_FAILED                   = 7;
-    /** @hide */
-    public static final int STOP_DISCOVERY_SUCCEEDED                = 8;
-
-    /** @hide */
-    public static final int REGISTER_SERVICE                        = 9;
-    /** @hide */
-    public static final int REGISTER_SERVICE_FAILED                 = 10;
-    /** @hide */
-    public static final int REGISTER_SERVICE_SUCCEEDED              = 11;
-
-    /** @hide */
-    public static final int UNREGISTER_SERVICE                      = 12;
-    /** @hide */
-    public static final int UNREGISTER_SERVICE_FAILED               = 13;
-    /** @hide */
-    public static final int UNREGISTER_SERVICE_SUCCEEDED            = 14;
-
-    /** @hide */
-    public static final int RESOLVE_SERVICE                         = 15;
-    /** @hide */
-    public static final int RESOLVE_SERVICE_FAILED                  = 16;
-    /** @hide */
-    public static final int RESOLVE_SERVICE_SUCCEEDED               = 17;
-
-    /** @hide */
-    public static final int DAEMON_CLEANUP                          = 18;
-
-    /** @hide */
-    public static final int DAEMON_STARTUP                          = 19;
-
-    /** @hide */
-    public static final int ENABLE                                  = 20;
-    /** @hide */
-    public static final int DISABLE                                 = 21;
-
-    /** @hide */
-    public static final int NATIVE_DAEMON_EVENT                     = 22;
-
-    /** @hide */
-    public static final int REGISTER_CLIENT                         = 23;
-    /** @hide */
-    public static final int UNREGISTER_CLIENT                       = 24;
-
-    /** Dns based service discovery protocol */
-    public static final int PROTOCOL_DNS_SD = 0x0001;
-
-    private static final SparseArray<String> EVENT_NAMES = new SparseArray<>();
-    static {
-        EVENT_NAMES.put(DISCOVER_SERVICES, "DISCOVER_SERVICES");
-        EVENT_NAMES.put(DISCOVER_SERVICES_STARTED, "DISCOVER_SERVICES_STARTED");
-        EVENT_NAMES.put(DISCOVER_SERVICES_FAILED, "DISCOVER_SERVICES_FAILED");
-        EVENT_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
-        EVENT_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
-        EVENT_NAMES.put(STOP_DISCOVERY, "STOP_DISCOVERY");
-        EVENT_NAMES.put(STOP_DISCOVERY_FAILED, "STOP_DISCOVERY_FAILED");
-        EVENT_NAMES.put(STOP_DISCOVERY_SUCCEEDED, "STOP_DISCOVERY_SUCCEEDED");
-        EVENT_NAMES.put(REGISTER_SERVICE, "REGISTER_SERVICE");
-        EVENT_NAMES.put(REGISTER_SERVICE_FAILED, "REGISTER_SERVICE_FAILED");
-        EVENT_NAMES.put(REGISTER_SERVICE_SUCCEEDED, "REGISTER_SERVICE_SUCCEEDED");
-        EVENT_NAMES.put(UNREGISTER_SERVICE, "UNREGISTER_SERVICE");
-        EVENT_NAMES.put(UNREGISTER_SERVICE_FAILED, "UNREGISTER_SERVICE_FAILED");
-        EVENT_NAMES.put(UNREGISTER_SERVICE_SUCCEEDED, "UNREGISTER_SERVICE_SUCCEEDED");
-        EVENT_NAMES.put(RESOLVE_SERVICE, "RESOLVE_SERVICE");
-        EVENT_NAMES.put(RESOLVE_SERVICE_FAILED, "RESOLVE_SERVICE_FAILED");
-        EVENT_NAMES.put(RESOLVE_SERVICE_SUCCEEDED, "RESOLVE_SERVICE_SUCCEEDED");
-        EVENT_NAMES.put(DAEMON_CLEANUP, "DAEMON_CLEANUP");
-        EVENT_NAMES.put(DAEMON_STARTUP, "DAEMON_STARTUP");
-        EVENT_NAMES.put(ENABLE, "ENABLE");
-        EVENT_NAMES.put(DISABLE, "DISABLE");
-        EVENT_NAMES.put(NATIVE_DAEMON_EVENT, "NATIVE_DAEMON_EVENT");
-    }
-
-    /** @hide */
-    public static String nameOf(int event) {
-        String name = EVENT_NAMES.get(event);
-        if (name == null) {
-            return Integer.toString(event);
-        }
-        return name;
-    }
-
-    private static final int FIRST_LISTENER_KEY = 1;
-
-    private final INsdServiceConnector mService;
-    private final Context mContext;
-
-    private int mListenerKey = FIRST_LISTENER_KEY;
-    @GuardedBy("mMapLock")
-    private final SparseArray mListenerMap = new SparseArray();
-    @GuardedBy("mMapLock")
-    private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
-    @GuardedBy("mMapLock")
-    private final SparseArray<Executor> mExecutorMap = new SparseArray<>();
-    private final Object mMapLock = new Object();
-    // Map of listener key sent by client -> per-network discovery tracker
-    @GuardedBy("mPerNetworkDiscoveryMap")
-    private final ArrayMap<Integer, PerNetworkDiscoveryTracker>
-            mPerNetworkDiscoveryMap = new ArrayMap<>();
-
-    private final ServiceHandler mHandler;
-
-    private class PerNetworkDiscoveryTracker {
-        final String mServiceType;
-        final int mProtocolType;
-        final DiscoveryListener mBaseListener;
-        final Executor mBaseExecutor;
-        final ArrayMap<Network, DelegatingDiscoveryListener> mPerNetworkListeners =
-                new ArrayMap<>();
-
-        final NetworkCallback mNetworkCb = new NetworkCallback() {
-            @Override
-            public void onAvailable(@NonNull Network network) {
-                final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener(
-                        network, mBaseListener);
-                mPerNetworkListeners.put(network, wrappedListener);
-                discoverServices(mServiceType, mProtocolType, network, mBaseExecutor,
-                        wrappedListener);
-            }
-
-            @Override
-            public void onLost(@NonNull Network network) {
-                final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network);
-                if (listener == null) return;
-                listener.notifyAllServicesLost();
-                // Listener will be removed from map in discovery stopped callback
-                stopServiceDiscovery(listener);
-            }
-        };
-
-        // Accessed from mHandler
-        private boolean mStopRequested;
-
-        public void start(@NonNull NetworkRequest request) {
-            final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
-            cm.registerNetworkCallback(request, mNetworkCb, mHandler);
-            mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType));
-        }
-
-        /**
-         * Stop discovery on all networks tracked by this class.
-         *
-         * This will request all underlying listeners to stop, and the last one to stop will call
-         * onDiscoveryStopped or onStopDiscoveryFailed.
-         *
-         * Must be called on the handler thread.
-         */
-        public void requestStop() {
-            mHandler.post(() -> {
-                mStopRequested = true;
-                final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
-                cm.unregisterNetworkCallback(mNetworkCb);
-                if (mPerNetworkListeners.size() == 0) {
-                    mBaseListener.onDiscoveryStopped(mServiceType);
-                    return;
-                }
-                for (int i = 0; i < mPerNetworkListeners.size(); i++) {
-                    final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i);
-                    stopServiceDiscovery(listener);
-                }
-            });
-        }
-
-        private PerNetworkDiscoveryTracker(String serviceType, int protocolType,
-                Executor baseExecutor, DiscoveryListener baseListener) {
-            mServiceType = serviceType;
-            mProtocolType = protocolType;
-            mBaseExecutor = baseExecutor;
-            mBaseListener = baseListener;
-        }
-
-        /**
-         * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a
-         * network is lost.
-         *
-         * Service lost notifications only contain service name, type and network, so only track
-         * that information (Network is known from the listener). This also implements
-         * equals/hashCode for usage in maps.
-         */
-        private class TrackedNsdInfo {
-            private final String mServiceName;
-            private final String mServiceType;
-            TrackedNsdInfo(NsdServiceInfo info) {
-                mServiceName = info.getServiceName();
-                mServiceType = info.getServiceType();
-            }
-
-            @Override
-            public int hashCode() {
-                return Objects.hash(mServiceName, mServiceType);
-            }
-
-            @Override
-            public boolean equals(Object obj) {
-                if (!(obj instanceof TrackedNsdInfo)) return false;
-                final TrackedNsdInfo other = (TrackedNsdInfo) obj;
-                return Objects.equals(mServiceName, other.mServiceName)
-                        && Objects.equals(mServiceType, other.mServiceType);
-            }
-        }
-
-        private class DelegatingDiscoveryListener implements DiscoveryListener {
-            private final Network mNetwork;
-            private final DiscoveryListener mWrapped;
-            private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>();
-
-            private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) {
-                mNetwork = network;
-                mWrapped = listener;
-            }
-
-            void notifyAllServicesLost() {
-                for (int i = 0; i < mFoundInfo.size(); i++) {
-                    final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i);
-                    final NsdServiceInfo serviceInfo = new NsdServiceInfo(
-                            trackedInfo.mServiceName, trackedInfo.mServiceType);
-                    serviceInfo.setNetwork(mNetwork);
-                    mWrapped.onServiceLost(serviceInfo);
-                }
-            }
-
-            @Override
-            public void onStartDiscoveryFailed(String serviceType, int errorCode) {
-                // The delegated listener is used when NsdManager takes care of starting/stopping
-                // discovery on multiple networks. Failure to start on one network is not a global
-                // failure to be reported up, as other networks may succeed: just log.
-                Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork
-                        + " with code " + errorCode);
-                mPerNetworkListeners.remove(mNetwork);
-            }
-
-            @Override
-            public void onDiscoveryStarted(String serviceType) {
-                // Wrapped listener was called upon registration, it is not called for discovery
-                // on each network
-            }
-
-            @Override
-            public void onStopDiscoveryFailed(String serviceType, int errorCode) {
-                Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork
-                        + " with code " + errorCode);
-                mPerNetworkListeners.remove(mNetwork);
-                if (mStopRequested && mPerNetworkListeners.size() == 0) {
-                    // Do not report onStopDiscoveryFailed when some underlying listeners failed:
-                    // this does not mean that all listeners did, and onStopDiscoveryFailed is not
-                    // actionable anyway. Just report that discovery stopped.
-                    mWrapped.onDiscoveryStopped(serviceType);
-                }
-            }
-
-            @Override
-            public void onDiscoveryStopped(String serviceType) {
-                mPerNetworkListeners.remove(mNetwork);
-                if (mStopRequested && mPerNetworkListeners.size() == 0) {
-                    mWrapped.onDiscoveryStopped(serviceType);
-                }
-            }
-
-            @Override
-            public void onServiceFound(NsdServiceInfo serviceInfo) {
-                mFoundInfo.add(new TrackedNsdInfo(serviceInfo));
-                mWrapped.onServiceFound(serviceInfo);
-            }
-
-            @Override
-            public void onServiceLost(NsdServiceInfo serviceInfo) {
-                mFoundInfo.remove(new TrackedNsdInfo(serviceInfo));
-                mWrapped.onServiceLost(serviceInfo);
-            }
-        }
-    }
-
-    /**
-     * Create a new Nsd instance. Applications use
-     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
-     * {@link android.content.Context#NSD_SERVICE Context.NSD_SERVICE}.
-     * @param service the Binder interface
-     * @hide - hide this because it takes in a parameter of type INsdManager, which
-     * is a system private class.
-     */
-    public NsdManager(Context context, INsdManager service) {
-        mContext = context;
-
-        HandlerThread t = new HandlerThread("NsdManager");
-        t.start();
-        mHandler = new ServiceHandler(t.getLooper());
-
-        try {
-            mService = service.connect(new NsdCallbackImpl(mHandler));
-        } catch (RemoteException e) {
-            throw new RuntimeException("Failed to connect to NsdService");
-        }
-
-        // Only proactively start the daemon if the target SDK < S, otherwise the internal service
-        // would automatically start/stop the native daemon as needed.
-        if (!CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
-            try {
-                mService.startDaemon();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to proactively start daemon");
-                // Continue: the daemon can still be started on-demand later
-            }
-        }
-    }
-
-    private static class NsdCallbackImpl extends INsdManagerCallback.Stub {
-        private final Handler mServHandler;
-
-        NsdCallbackImpl(Handler serviceHandler) {
-            mServHandler = serviceHandler;
-        }
-
-        private void sendInfo(int message, int listenerKey, NsdServiceInfo info) {
-            mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info));
-        }
-
-        private void sendError(int message, int listenerKey, int error) {
-            mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey));
-        }
-
-        private void sendNoArg(int message, int listenerKey) {
-            mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey));
-        }
-
-        @Override
-        public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
-            sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info);
-        }
-
-        @Override
-        public void onDiscoverServicesFailed(int listenerKey, int error) {
-            sendError(DISCOVER_SERVICES_FAILED, listenerKey, error);
-        }
-
-        @Override
-        public void onServiceFound(int listenerKey, NsdServiceInfo info) {
-            sendInfo(SERVICE_FOUND, listenerKey, info);
-        }
-
-        @Override
-        public void onServiceLost(int listenerKey, NsdServiceInfo info) {
-            sendInfo(SERVICE_LOST, listenerKey, info);
-        }
-
-        @Override
-        public void onStopDiscoveryFailed(int listenerKey, int error) {
-            sendError(STOP_DISCOVERY_FAILED, listenerKey, error);
-        }
-
-        @Override
-        public void onStopDiscoverySucceeded(int listenerKey) {
-            sendNoArg(STOP_DISCOVERY_SUCCEEDED, listenerKey);
-        }
-
-        @Override
-        public void onRegisterServiceFailed(int listenerKey, int error) {
-            sendError(REGISTER_SERVICE_FAILED, listenerKey, error);
-        }
-
-        @Override
-        public void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
-            sendInfo(REGISTER_SERVICE_SUCCEEDED, listenerKey, info);
-        }
-
-        @Override
-        public void onUnregisterServiceFailed(int listenerKey, int error) {
-            sendError(UNREGISTER_SERVICE_FAILED, listenerKey, error);
-        }
-
-        @Override
-        public void onUnregisterServiceSucceeded(int listenerKey) {
-            sendNoArg(UNREGISTER_SERVICE_SUCCEEDED, listenerKey);
-        }
-
-        @Override
-        public void onResolveServiceFailed(int listenerKey, int error) {
-            sendError(RESOLVE_SERVICE_FAILED, listenerKey, error);
-        }
-
-        @Override
-        public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
-            sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info);
-        }
-    }
-
-    /**
-     * Failures are passed with {@link RegistrationListener#onRegistrationFailed},
-     * {@link RegistrationListener#onUnregistrationFailed},
-     * {@link DiscoveryListener#onStartDiscoveryFailed},
-     * {@link DiscoveryListener#onStopDiscoveryFailed} or {@link ResolveListener#onResolveFailed}.
-     *
-     * Indicates that the operation failed due to an internal error.
-     */
-    public static final int FAILURE_INTERNAL_ERROR               = 0;
-
-    /**
-     * Indicates that the operation failed because it is already active.
-     */
-    public static final int FAILURE_ALREADY_ACTIVE              = 3;
-
-    /**
-     * Indicates that the operation failed because the maximum outstanding
-     * requests from the applications have reached.
-     */
-    public static final int FAILURE_MAX_LIMIT                   = 4;
-
-    /** Interface for callback invocation for service discovery */
-    public interface DiscoveryListener {
-
-        public void onStartDiscoveryFailed(String serviceType, int errorCode);
-
-        public void onStopDiscoveryFailed(String serviceType, int errorCode);
-
-        public void onDiscoveryStarted(String serviceType);
-
-        public void onDiscoveryStopped(String serviceType);
-
-        public void onServiceFound(NsdServiceInfo serviceInfo);
-
-        public void onServiceLost(NsdServiceInfo serviceInfo);
-    }
-
-    /** Interface for callback invocation for service registration */
-    public interface RegistrationListener {
-
-        public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode);
-
-        public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode);
-
-        public void onServiceRegistered(NsdServiceInfo serviceInfo);
-
-        public void onServiceUnregistered(NsdServiceInfo serviceInfo);
-    }
-
-    /** Interface for callback invocation for service resolution */
-    public interface ResolveListener {
-
-        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode);
-
-        public void onServiceResolved(NsdServiceInfo serviceInfo);
-    }
-
-    @VisibleForTesting
-    class ServiceHandler extends Handler {
-        ServiceHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message message) {
-            final int what = message.what;
-            final int key = message.arg2;
-            final Object listener;
-            final NsdServiceInfo ns;
-            final Executor executor;
-            synchronized (mMapLock) {
-                listener = mListenerMap.get(key);
-                ns = mServiceMap.get(key);
-                executor = mExecutorMap.get(key);
-            }
-            if (listener == null) {
-                Log.d(TAG, "Stale key " + message.arg2);
-                return;
-            }
-            if (DBG) {
-                Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns);
-            }
-            switch (what) {
-                case DISCOVER_SERVICES_STARTED:
-                    final String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
-                    executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStarted(s));
-                    break;
-                case DISCOVER_SERVICES_FAILED:
-                    removeListener(key);
-                    executor.execute(() -> ((DiscoveryListener) listener).onStartDiscoveryFailed(
-                            getNsdServiceInfoType(ns), message.arg1));
-                    break;
-                case SERVICE_FOUND:
-                    executor.execute(() -> ((DiscoveryListener) listener).onServiceFound(
-                            (NsdServiceInfo) message.obj));
-                    break;
-                case SERVICE_LOST:
-                    executor.execute(() -> ((DiscoveryListener) listener).onServiceLost(
-                            (NsdServiceInfo) message.obj));
-                    break;
-                case STOP_DISCOVERY_FAILED:
-                    // TODO: failure to stop discovery should be internal and retried internally, as
-                    // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED
-                    removeListener(key);
-                    executor.execute(() -> ((DiscoveryListener) listener).onStopDiscoveryFailed(
-                            getNsdServiceInfoType(ns), message.arg1));
-                    break;
-                case STOP_DISCOVERY_SUCCEEDED:
-                    removeListener(key);
-                    executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStopped(
-                            getNsdServiceInfoType(ns)));
-                    break;
-                case REGISTER_SERVICE_FAILED:
-                    removeListener(key);
-                    executor.execute(() -> ((RegistrationListener) listener).onRegistrationFailed(
-                            ns, message.arg1));
-                    break;
-                case REGISTER_SERVICE_SUCCEEDED:
-                    executor.execute(() -> ((RegistrationListener) listener).onServiceRegistered(
-                            (NsdServiceInfo) message.obj));
-                    break;
-                case UNREGISTER_SERVICE_FAILED:
-                    removeListener(key);
-                    executor.execute(() -> ((RegistrationListener) listener).onUnregistrationFailed(
-                            ns, message.arg1));
-                    break;
-                case UNREGISTER_SERVICE_SUCCEEDED:
-                    // TODO: do not unregister listener until service is unregistered, or provide
-                    // alternative way for unregistering ?
-                    removeListener(message.arg2);
-                    executor.execute(() -> ((RegistrationListener) listener).onServiceUnregistered(
-                            ns));
-                    break;
-                case RESOLVE_SERVICE_FAILED:
-                    removeListener(key);
-                    executor.execute(() -> ((ResolveListener) listener).onResolveFailed(
-                            ns, message.arg1));
-                    break;
-                case RESOLVE_SERVICE_SUCCEEDED:
-                    removeListener(key);
-                    executor.execute(() -> ((ResolveListener) listener).onServiceResolved(
-                            (NsdServiceInfo) message.obj));
-                    break;
-                default:
-                    Log.d(TAG, "Ignored " + message);
-                    break;
-            }
-        }
-    }
-
-    private int nextListenerKey() {
-        // Ensure mListenerKey >= FIRST_LISTENER_KEY;
-        mListenerKey = Math.max(FIRST_LISTENER_KEY, mListenerKey + 1);
-        return mListenerKey;
-    }
-
-    // Assert that the listener is not in the map, then add it and returns its key
-    private int putListener(Object listener, Executor e, NsdServiceInfo s) {
-        checkListener(listener);
-        final int key;
-        synchronized (mMapLock) {
-            int valueIndex = mListenerMap.indexOfValue(listener);
-            if (valueIndex != -1) {
-                throw new IllegalArgumentException("listener already in use");
-            }
-            key = nextListenerKey();
-            mListenerMap.put(key, listener);
-            mServiceMap.put(key, s);
-            mExecutorMap.put(key, e);
-        }
-        return key;
-    }
-
-    private void removeListener(int key) {
-        synchronized (mMapLock) {
-            mListenerMap.remove(key);
-            mServiceMap.remove(key);
-            mExecutorMap.remove(key);
-        }
-    }
-
-    private int getListenerKey(Object listener) {
-        checkListener(listener);
-        synchronized (mMapLock) {
-            int valueIndex = mListenerMap.indexOfValue(listener);
-            if (valueIndex == -1) {
-                throw new IllegalArgumentException("listener not registered");
-            }
-            return mListenerMap.keyAt(valueIndex);
-        }
-    }
-
-    private static String getNsdServiceInfoType(NsdServiceInfo s) {
-        if (s == null) return "?";
-        return s.getServiceType();
-    }
-
-    /**
-     * Register a service to be discovered by other services.
-     *
-     * <p> The function call immediately returns after sending a request to register service
-     * to the framework. The application is notified of a successful registration
-     * through the callback {@link RegistrationListener#onServiceRegistered} or a failure
-     * through {@link RegistrationListener#onRegistrationFailed}.
-     *
-     * <p> The application should call {@link #unregisterService} when the service
-     * registration is no longer required, and/or whenever the application is stopped.
-     *
-     * @param serviceInfo The service being registered
-     * @param protocolType The service discovery protocol
-     * @param listener The listener notifies of a successful registration and is used to
-     * unregister this service through a call on {@link #unregisterService}. Cannot be null.
-     * Cannot be in use for an active service registration.
-     */
-    public void registerService(NsdServiceInfo serviceInfo, int protocolType,
-            RegistrationListener listener) {
-        registerService(serviceInfo, protocolType, Runnable::run, listener);
-    }
-
-    /**
-     * Register a service to be discovered by other services.
-     *
-     * <p> The function call immediately returns after sending a request to register service
-     * to the framework. The application is notified of a successful registration
-     * through the callback {@link RegistrationListener#onServiceRegistered} or a failure
-     * through {@link RegistrationListener#onRegistrationFailed}.
-     *
-     * <p> The application should call {@link #unregisterService} when the service
-     * registration is no longer required, and/or whenever the application is stopped.
-     * @param serviceInfo The service being registered
-     * @param protocolType The service discovery protocol
-     * @param executor Executor to run listener callbacks with
-     * @param listener The listener notifies of a successful registration and is used to
-     * unregister this service through a call on {@link #unregisterService}. Cannot be null.
-     */
-    public void registerService(@NonNull NsdServiceInfo serviceInfo, int protocolType,
-            @NonNull Executor executor, @NonNull RegistrationListener listener) {
-        if (serviceInfo.getPort() <= 0) {
-            throw new IllegalArgumentException("Invalid port number");
-        }
-        checkServiceInfo(serviceInfo);
-        checkProtocol(protocolType);
-        int key = putListener(listener, executor, serviceInfo);
-        try {
-            mService.registerService(key, serviceInfo);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Unregister a service registered through {@link #registerService}. A successful
-     * unregister is notified to the application with a call to
-     * {@link RegistrationListener#onServiceUnregistered}.
-     *
-     * @param listener This should be the listener object that was passed to
-     * {@link #registerService}. It identifies the service that should be unregistered
-     * and notifies of a successful or unsuccessful unregistration via the listener
-     * callbacks.  In API versions 20 and above, the listener object may be used for
-     * another service registration once the callback has been called.  In API versions <= 19,
-     * there is no entirely reliable way to know when a listener may be re-used, and a new
-     * listener should be created for each service registration request.
-     */
-    public void unregisterService(RegistrationListener listener) {
-        int id = getListenerKey(listener);
-        try {
-            mService.unregisterService(id);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Initiate service discovery to browse for instances of a service type. Service discovery
-     * consumes network bandwidth and will continue until the application calls
-     * {@link #stopServiceDiscovery}.
-     *
-     * <p> The function call immediately returns after sending a request to start service
-     * discovery to the framework. The application is notified of a success to initiate
-     * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
-     * through {@link DiscoveryListener#onStartDiscoveryFailed}.
-     *
-     * <p> Upon successful start, application is notified when a service is found with
-     * {@link DiscoveryListener#onServiceFound} or when a service is lost with
-     * {@link DiscoveryListener#onServiceLost}.
-     *
-     * <p> Upon failure to start, service discovery is not active and application does
-     * not need to invoke {@link #stopServiceDiscovery}
-     *
-     * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
-     * service type is no longer required, and/or whenever the application is paused or
-     * stopped.
-     *
-     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
-     * http services or "_ipp._tcp" for printers
-     * @param protocolType The service discovery protocol
-     * @param listener  The listener notifies of a successful discovery and is used
-     * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
-     * Cannot be null. Cannot be in use for an active service discovery.
-     */
-    public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
-        discoverServices(serviceType, protocolType, (Network) null, Runnable::run, listener);
-    }
-
-    /**
-     * Initiate service discovery to browse for instances of a service type. Service discovery
-     * consumes network bandwidth and will continue until the application calls
-     * {@link #stopServiceDiscovery}.
-     *
-     * <p> The function call immediately returns after sending a request to start service
-     * discovery to the framework. The application is notified of a success to initiate
-     * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
-     * through {@link DiscoveryListener#onStartDiscoveryFailed}.
-     *
-     * <p> Upon successful start, application is notified when a service is found with
-     * {@link DiscoveryListener#onServiceFound} or when a service is lost with
-     * {@link DiscoveryListener#onServiceLost}.
-     *
-     * <p> Upon failure to start, service discovery is not active and application does
-     * not need to invoke {@link #stopServiceDiscovery}
-     *
-     * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
-     * service type is no longer required, and/or whenever the application is paused or
-     * stopped.
-     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
-     * http services or "_ipp._tcp" for printers
-     * @param protocolType The service discovery protocol
-     * @param network Network to discover services on, or null to discover on all available networks
-     * @param executor Executor to run listener callbacks with
-     * @param listener  The listener notifies of a successful discovery and is used
-     * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
-     */
-    public void discoverServices(@NonNull String serviceType, int protocolType,
-            @Nullable Network network, @NonNull Executor executor,
-            @NonNull DiscoveryListener listener) {
-        if (TextUtils.isEmpty(serviceType)) {
-            throw new IllegalArgumentException("Service type cannot be empty");
-        }
-        checkProtocol(protocolType);
-
-        NsdServiceInfo s = new NsdServiceInfo();
-        s.setServiceType(serviceType);
-        s.setNetwork(network);
-
-        int key = putListener(listener, executor, s);
-        try {
-            mService.discoverServices(key, s);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Initiate service discovery to browse for instances of a service type. Service discovery
-     * consumes network bandwidth and will continue until the application calls
-     * {@link #stopServiceDiscovery}.
-     *
-     * <p> The function call immediately returns after sending a request to start service
-     * discovery to the framework. The application is notified of a success to initiate
-     * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
-     * through {@link DiscoveryListener#onStartDiscoveryFailed}.
-     *
-     * <p> Upon successful start, application is notified when a service is found with
-     * {@link DiscoveryListener#onServiceFound} or when a service is lost with
-     * {@link DiscoveryListener#onServiceLost}.
-     *
-     * <p> Upon failure to start, service discovery is not active and application does
-     * not need to invoke {@link #stopServiceDiscovery}
-     *
-     * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
-     * service type is no longer required, and/or whenever the application is paused or
-     * stopped.
-     *
-     * <p> During discovery, new networks may connect or existing networks may disconnect - for
-     * example if wifi is reconnected. When a service was found on a network that disconnects,
-     * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that
-     * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called
-     * for services found on that network. Applications that do not want to track networks
-     * themselves are encouraged to use this method instead of other overloads of
-     * {@code discoverServices}, as they will receive proper notifications when a service becomes
-     * available or unavailable due to network changes.
-     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
-     * http services or "_ipp._tcp" for printers
-     * @param protocolType The service discovery protocol
-     * @param networkRequest Request specifying networks that should be considered when discovering
-     * @param executor Executor to run listener callbacks with
-     * @param listener  The listener notifies of a successful discovery and is used
-     * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
-     */
-    @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
-    public void discoverServices(@NonNull String serviceType, int protocolType,
-            @NonNull NetworkRequest networkRequest, @NonNull Executor executor,
-            @NonNull DiscoveryListener listener) {
-        if (TextUtils.isEmpty(serviceType)) {
-            throw new IllegalArgumentException("Service type cannot be empty");
-        }
-        Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null");
-        checkProtocol(protocolType);
-
-        NsdServiceInfo s = new NsdServiceInfo();
-        s.setServiceType(serviceType);
-
-        final int baseListenerKey = putListener(listener, executor, s);
-
-        final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker(
-                serviceType, protocolType, executor, listener);
-
-        synchronized (mPerNetworkDiscoveryMap) {
-            mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo);
-            discoveryInfo.start(networkRequest);
-        }
-    }
-
-    /**
-     * Stop service discovery initiated with {@link #discoverServices}.  An active service
-     * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
-     * and it stays active until the application invokes a stop service discovery. A successful
-     * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}.
-     *
-     * <p> Upon failure to stop service discovery, application is notified through
-     * {@link DiscoveryListener#onStopDiscoveryFailed}.
-     *
-     * @param listener This should be the listener object that was passed to {@link #discoverServices}.
-     * It identifies the discovery that should be stopped and notifies of a successful or
-     * unsuccessful stop.  In API versions 20 and above, the listener object may be used for
-     * another service discovery once the callback has been called.  In API versions <= 19,
-     * there is no entirely reliable way to know when a listener may be re-used, and a new
-     * listener should be created for each service discovery request.
-     */
-    public void stopServiceDiscovery(DiscoveryListener listener) {
-        int id = getListenerKey(listener);
-        // If this is a PerNetworkDiscovery request, handle it as such
-        synchronized (mPerNetworkDiscoveryMap) {
-            final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id);
-            if (info != null) {
-                info.requestStop();
-                return;
-            }
-        }
-        try {
-            mService.stopDiscovery(id);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Resolve a discovered service. An application can resolve a service right before
-     * establishing a connection to fetch the IP and port details on which to setup
-     * the connection.
-     *
-     * @param serviceInfo service to be resolved
-     * @param listener to receive callback upon success or failure. Cannot be null.
-     * Cannot be in use for an active service resolution.
-     */
-    public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
-        resolveService(serviceInfo, Runnable::run, listener);
-    }
-
-    /**
-     * Resolve a discovered service. An application can resolve a service right before
-     * establishing a connection to fetch the IP and port details on which to setup
-     * the connection.
-     * @param serviceInfo service to be resolved
-     * @param executor Executor to run listener callbacks with
-     * @param listener to receive callback upon success or failure.
-     */
-    public void resolveService(@NonNull NsdServiceInfo serviceInfo,
-            @NonNull Executor executor, @NonNull ResolveListener listener) {
-        checkServiceInfo(serviceInfo);
-        int key = putListener(listener, executor, serviceInfo);
-        try {
-            mService.resolveService(key, serviceInfo);
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-    }
-
-    private static void checkListener(Object listener) {
-        Objects.requireNonNull(listener, "listener cannot be null");
-    }
-
-    private static void checkProtocol(int protocolType) {
-        if (protocolType != PROTOCOL_DNS_SD) {
-            throw new IllegalArgumentException("Unsupported protocol");
-        }
-    }
-
-    private static void checkServiceInfo(NsdServiceInfo serviceInfo) {
-        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/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
deleted file mode 100644
index 8506db1..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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.nsd;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.net.Network;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Base64;
-import android.util.Log;
-
-import java.io.UnsupportedEncodingException;
-import java.net.InetAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * A class representing service information for network service discovery
- * {@see NsdManager}
- */
-public final class NsdServiceInfo implements Parcelable {
-
-    private static final String TAG = "NsdServiceInfo";
-
-    private String mServiceName;
-
-    private String mServiceType;
-
-    private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<>();
-
-    private InetAddress mHost;
-
-    private int mPort;
-
-    @Nullable
-    private Network mNetwork;
-
-    public NsdServiceInfo() {
-    }
-
-    /** @hide */
-    public NsdServiceInfo(String sn, String rt) {
-        mServiceName = sn;
-        mServiceType = rt;
-    }
-
-    /** Get the service name */
-    public String getServiceName() {
-        return mServiceName;
-    }
-
-    /** Set the service name */
-    public void setServiceName(String s) {
-        mServiceName = s;
-    }
-
-    /** Get the service type */
-    public String getServiceType() {
-        return mServiceType;
-    }
-
-    /** Set the service type */
-    public void setServiceType(String s) {
-        mServiceType = s;
-    }
-
-    /** Get the host address. The host address is valid for a resolved service. */
-    public InetAddress getHost() {
-        return mHost;
-    }
-
-    /** Set the host address */
-    public void setHost(InetAddress s) {
-        mHost = s;
-    }
-
-    /** Get port number. The port number is valid for a resolved service. */
-    public int getPort() {
-        return mPort;
-    }
-
-    /** Set port number */
-    public void setPort(int p) {
-        mPort = p;
-    }
-
-    /**
-     * Unpack txt information from a base-64 encoded byte array.
-     *
-     * @param rawRecords The raw base64 encoded records string read from netd.
-     *
-     * @hide
-     */
-    public void setTxtRecords(@NonNull String rawRecords) {
-        byte[] txtRecordsRawBytes = Base64.decode(rawRecords, Base64.DEFAULT);
-
-        // There can be multiple TXT records after each other. Each record has to following format:
-        //
-        // byte                  type                  required   meaning
-        // -------------------   -------------------   --------   ----------------------------------
-        // 0                     unsigned 8 bit        yes        size of record excluding this byte
-        // 1 - n                 ASCII but not '='     yes        key
-        // n + 1                 '='                   optional   separator of key and value
-        // n + 2 - record size   uninterpreted bytes   optional   value
-        //
-        // Example legal records:
-        // [11, 'm', 'y', 'k', 'e', 'y', '=', 0x0, 0x4, 0x65, 0x7, 0xff]
-        // [17, 'm', 'y', 'K', 'e', 'y', 'W', 'i', 't', 'h', 'N', 'o', 'V', 'a', 'l', 'u', 'e', '=']
-        // [12, 'm', 'y', 'B', 'o', 'o', 'l', 'e', 'a', 'n', 'K', 'e', 'y']
-        //
-        // Example corrupted records
-        // [3, =, 1, 2]    <- key is empty
-        // [3, 0, =, 2]    <- key contains non-ASCII character. We handle this by replacing the
-        //                    invalid characters instead of skipping the record.
-        // [30, 'a', =, 2] <- length exceeds total left over bytes in the TXT records array, we
-        //                    handle this by reducing the length of the record as needed.
-        int pos = 0;
-        while (pos < txtRecordsRawBytes.length) {
-            // recordLen is an unsigned 8 bit value
-            int recordLen = txtRecordsRawBytes[pos] & 0xff;
-            pos += 1;
-
-            try {
-                if (recordLen == 0) {
-                    throw new IllegalArgumentException("Zero sized txt record");
-                } else if (pos + recordLen > txtRecordsRawBytes.length) {
-                    Log.w(TAG, "Corrupt record length (pos = " + pos + "): " + recordLen);
-                    recordLen = txtRecordsRawBytes.length - pos;
-                }
-
-                // Decode key-value records
-                String key = null;
-                byte[] value = null;
-                int valueLen = 0;
-                for (int i = pos; i < pos + recordLen; i++) {
-                    if (key == null) {
-                        if (txtRecordsRawBytes[i] == '=') {
-                            key = new String(txtRecordsRawBytes, pos, i - pos,
-                                    StandardCharsets.US_ASCII);
-                        }
-                    } else {
-                        if (value == null) {
-                            value = new byte[recordLen - key.length() - 1];
-                        }
-                        value[valueLen] = txtRecordsRawBytes[i];
-                        valueLen++;
-                    }
-                }
-
-                // If '=' was not found we have a boolean record
-                if (key == null) {
-                    key = new String(txtRecordsRawBytes, pos, recordLen, StandardCharsets.US_ASCII);
-                }
-
-                if (TextUtils.isEmpty(key)) {
-                    // Empty keys are not allowed (RFC6763 6.4)
-                    throw new IllegalArgumentException("Invalid txt record (key is empty)");
-                }
-
-                if (getAttributes().containsKey(key)) {
-                    // When we have a duplicate record, the later ones are ignored (RFC6763 6.4)
-                    throw new IllegalArgumentException("Invalid txt record (duplicate key \"" + key + "\")");
-                }
-
-                setAttribute(key, value);
-            } catch (IllegalArgumentException e) {
-                Log.e(TAG, "While parsing txt records (pos = " + pos + "): " + e.getMessage());
-            }
-
-            pos += recordLen;
-        }
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public void setAttribute(String key, byte[] value) {
-        if (TextUtils.isEmpty(key)) {
-            throw new IllegalArgumentException("Key cannot be empty");
-        }
-
-        // Key must be printable US-ASCII, excluding =.
-        for (int i = 0; i < key.length(); ++i) {
-            char character = key.charAt(i);
-            if (character < 0x20 || character > 0x7E) {
-                throw new IllegalArgumentException("Key strings must be printable US-ASCII");
-            } else if (character == 0x3D) {
-                throw new IllegalArgumentException("Key strings must not include '='");
-            }
-        }
-
-        // Key length + value length must be < 255.
-        if (key.length() + (value == null ? 0 : value.length) >= 255) {
-            throw new IllegalArgumentException("Key length + value length must be < 255 bytes");
-        }
-
-        // Warn if key is > 9 characters, as recommended by RFC 6763 section 6.4.
-        if (key.length() > 9) {
-            Log.w(TAG, "Key lengths > 9 are discouraged: " + key);
-        }
-
-        // Check against total TXT record size limits.
-        // Arbitrary 400 / 1300 byte limits taken from RFC 6763 section 6.2.
-        int txtRecordSize = getTxtRecordSize();
-        int futureSize = txtRecordSize + key.length() + (value == null ? 0 : value.length) + 2;
-        if (futureSize > 1300) {
-            throw new IllegalArgumentException("Total length of attributes must be < 1300 bytes");
-        } else if (futureSize > 400) {
-            Log.w(TAG, "Total length of all attributes exceeds 400 bytes; truncation may occur");
-        }
-
-        mTxtRecord.put(key, value);
-    }
-
-    /**
-     * Add a service attribute as a key/value pair.
-     *
-     * <p> Service attributes are included as DNS-SD TXT record pairs.
-     *
-     * <p> The key must be US-ASCII printable characters, excluding the '=' character.  Values may
-     * be UTF-8 strings or null.  The total length of key + value must be less than 255 bytes.
-     *
-     * <p> Keys should be short, ideally no more than 9 characters, and unique per instance of
-     * {@link NsdServiceInfo}.  Calling {@link #setAttribute} twice with the same key will overwrite
-     * first value.
-     */
-    public void setAttribute(String key, String value) {
-        try {
-            setAttribute(key, value == null ? (byte []) null : value.getBytes("UTF-8"));
-        } catch (UnsupportedEncodingException e) {
-            throw new IllegalArgumentException("Value must be UTF-8");
-        }
-    }
-
-    /** Remove an attribute by key */
-    public void removeAttribute(String key) {
-        mTxtRecord.remove(key);
-    }
-
-    /**
-     * Retrieve attributes as a map of String keys to byte[] values. The attributes map is only
-     * valid for a resolved service.
-     *
-     * <p> The returned map is unmodifiable; changes must be made through {@link #setAttribute} and
-     * {@link #removeAttribute}.
-     */
-    public Map<String, byte[]> getAttributes() {
-        return Collections.unmodifiableMap(mTxtRecord);
-    }
-
-    private int getTxtRecordSize() {
-        int txtRecordSize = 0;
-        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
-            txtRecordSize += 2;  // One for the length byte, one for the = between key and value.
-            txtRecordSize += entry.getKey().length();
-            byte[] value = entry.getValue();
-            txtRecordSize += value == null ? 0 : value.length;
-        }
-        return txtRecordSize;
-    }
-
-    /** @hide */
-    public @NonNull byte[] getTxtRecord() {
-        int txtRecordSize = getTxtRecordSize();
-        if (txtRecordSize == 0) {
-            return new byte[]{};
-        }
-
-        byte[] txtRecord = new byte[txtRecordSize];
-        int ptr = 0;
-        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
-            String key = entry.getKey();
-            byte[] value = entry.getValue();
-
-            // One byte to record the length of this key/value pair.
-            txtRecord[ptr++] = (byte) (key.length() + (value == null ? 0 : value.length) + 1);
-
-            // The key, in US-ASCII.
-            // Note: use the StandardCharsets const here because it doesn't raise exceptions and we
-            // already know the key is ASCII at this point.
-            System.arraycopy(key.getBytes(StandardCharsets.US_ASCII), 0, txtRecord, ptr,
-                    key.length());
-            ptr += key.length();
-
-            // US-ASCII '=' character.
-            txtRecord[ptr++] = (byte)'=';
-
-            // The value, as any raw bytes.
-            if (value != null) {
-                System.arraycopy(value, 0, txtRecord, ptr, value.length);
-                ptr += value.length;
-            }
-        }
-        return txtRecord;
-    }
-
-    /**
-     * Get the network where the service can be found.
-     *
-     * This is never null if this {@link NsdServiceInfo} was obtained from
-     * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}.
-     */
-    @Nullable
-    public Network getNetwork() {
-        return mNetwork;
-    }
-
-    /**
-     * Set the network where the service can be found.
-     * @param network The network, or null to search for, or to announce, the service on all
-     *                connected networks.
-     */
-    public void setNetwork(@Nullable Network network) {
-        mNetwork = network;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("name: ").append(mServiceName)
-                .append(", type: ").append(mServiceType)
-                .append(", host: ").append(mHost)
-                .append(", port: ").append(mPort)
-                .append(", network: ").append(mNetwork);
-
-        byte[] txtRecord = getTxtRecord();
-        sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
-        return sb.toString();
-    }
-
-    /** Implement the Parcelable interface */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mServiceName);
-        dest.writeString(mServiceType);
-        if (mHost != null) {
-            dest.writeInt(1);
-            dest.writeByteArray(mHost.getAddress());
-        } else {
-            dest.writeInt(0);
-        }
-        dest.writeInt(mPort);
-
-        // TXT record key/value pairs.
-        dest.writeInt(mTxtRecord.size());
-        for (String key : mTxtRecord.keySet()) {
-            byte[] value = mTxtRecord.get(key);
-            if (value != null) {
-                dest.writeInt(1);
-                dest.writeInt(value.length);
-                dest.writeByteArray(value);
-            } else {
-                dest.writeInt(0);
-            }
-            dest.writeString(key);
-        }
-
-        dest.writeParcelable(mNetwork, 0);
-    }
-
-    /** Implement the Parcelable interface */
-    public static final @android.annotation.NonNull Creator<NsdServiceInfo> CREATOR =
-        new Creator<NsdServiceInfo>() {
-            public NsdServiceInfo createFromParcel(Parcel in) {
-                NsdServiceInfo info = new NsdServiceInfo();
-                info.mServiceName = in.readString();
-                info.mServiceType = in.readString();
-
-                if (in.readInt() == 1) {
-                    try {
-                        info.mHost = InetAddress.getByAddress(in.createByteArray());
-                    } catch (java.net.UnknownHostException e) {}
-                }
-
-                info.mPort = in.readInt();
-
-                // TXT record key/value pairs.
-                int recordCount = in.readInt();
-                for (int i = 0; i < recordCount; ++i) {
-                    byte[] valueArray = null;
-                    if (in.readInt() == 1) {
-                        int valueLength = in.readInt();
-                        valueArray = new byte[valueLength];
-                        in.readByteArray(valueArray);
-                    }
-                    info.mTxtRecord.put(in.readString(), valueArray);
-                }
-                info.mNetwork = in.readParcelable(null, Network.class);
-                return info;
-            }
-
-            public NsdServiceInfo[] newArray(int size) {
-                return new NsdServiceInfo[size];
-            }
-        };
-}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
deleted file mode 100644
index 4b799c5..0000000
--- a/packages/ConnectivityT/service/Android.bp
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
-    // See: http://go/android-license-faq
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// NetworkStats related libraries.
-
-filegroup {
-    name: "services.connectivity-netstats-sources",
-    srcs: [
-        "src/com/android/server/net/NetworkIdentity*.java",
-        "src/com/android/server/net/NetworkStats*.java",
-        "src/com/android/server/net/BpfInterfaceMapUpdater.java",
-        "src/com/android/server/net/InterfaceMapValue.java",
-        "src/com/android/server/net/CookieTagMapKey.java",
-        "src/com/android/server/net/CookieTagMapValue.java",
-        "src/com/android/server/net/StatsMapKey.java",
-        "src/com/android/server/net/StatsMapValue.java",
-        "src/com/android/server/net/UidStatsMapKey.java",
-    ],
-    path: "src",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-// For test code only.
-filegroup {
-    name: "lib_networkStatsFactory_native",
-    srcs: [
-        "jni/com_android_server_net_NetworkStatsFactory.cpp",
-    ],
-    path: "jni",
-    visibility: [
-        "//packages/modules/Connectivity:__subpackages__",
-    ],
-}
-
-filegroup {
-    name: "services.connectivity-netstats-jni-sources",
-    srcs: [
-        "jni/com_android_server_net_NetworkStatsFactory.cpp",
-        "jni/com_android_server_net_NetworkStatsService.cpp",
-    ],
-    path: "jni",
-    visibility: [
-        "//packages/modules/Connectivity:__subpackages__",
-    ],
-}
-
-// Nsd related libraries.
-
-filegroup {
-    name: "services.connectivity-nsd-sources",
-    srcs: [
-        "src/com/android/server/INativeDaemon*.java",
-        "src/com/android/server/NativeDaemon*.java",
-        "src/com/android/server/Nsd*.java",
-    ],
-    path: "src",
-    visibility: [
-        "//visibility:private",
-    ],
-}
-
-// 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/DelayedDiskWrite.java",
-        "src/com/android/server/net/IpConfigStore.java",
-    ],
-    path: "src",
-    visibility: [
-        "//frameworks/opt/net/ethernet/tests",
-    ],
-}
-
-// Connectivity-T common libraries.
-
-// TODO: remove this empty filegroup.
-filegroup {
-    name: "services.connectivity-tiramisu-sources",
-    srcs: [],
-    path: "src",
-    visibility: ["//frameworks/base/services/core"],
-}
-
-filegroup {
-    name: "services.connectivity-tiramisu-updatable-sources",
-    srcs: [
-        ":services.connectivity-ethernet-sources",
-        ":services.connectivity-ipsec-sources",
-        ":services.connectivity-netstats-sources",
-        ":services.connectivity-nsd-sources",
-    ],
-    path: "src",
-    visibility: [
-        "//packages/modules/Connectivity:__subpackages__",
-    ],
-}
-
-cc_library_shared {
-    name: "libcom_android_net_module_util_jni",
-    min_sdk_version: "30",
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-unused-parameter",
-        "-Wthread-safety",
-    ],
-    srcs: [
-        "jni/onload.cpp",
-    ],
-    stl: "libc++_static",
-    static_libs: [
-        "libnet_utils_device_common_bpfjni",
-    ],
-    shared_libs: [
-        "liblog",
-        "libnativehelper",
-    ],
-    apex_available: [
-        "//apex_available:platform",
-    ],
-}
diff --git a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
deleted file mode 100644
index 8b6526ff..0000000
--- a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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.
- */
-
-#define LOG_TAG "NetworkStats"
-
-#include <errno.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <vector>
-
-#include <jni.h>
-
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <nativehelper/ScopedLocalRef.h>
-#include <nativehelper/ScopedPrimitiveArray.h>
-
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "android-base/unique_fd.h"
-#include "bpf/BpfUtils.h"
-#include "netdbpf/BpfNetworkStats.h"
-
-using android::bpf::parseBpfNetworkStatsDetail;
-using android::bpf::stats_line;
-
-namespace android {
-
-static jclass gStringClass;
-
-static struct {
-    jfieldID size;
-    jfieldID capacity;
-    jfieldID iface;
-    jfieldID uid;
-    jfieldID set;
-    jfieldID tag;
-    jfieldID metered;
-    jfieldID roaming;
-    jfieldID defaultNetwork;
-    jfieldID rxBytes;
-    jfieldID rxPackets;
-    jfieldID txBytes;
-    jfieldID txPackets;
-    jfieldID operations;
-} gNetworkStatsClassInfo;
-
-static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
-    if (!grow) {
-        jobjectArray array = (jobjectArray)env->GetObjectField(obj, field);
-        if (array != NULL) {
-            return array;
-        }
-    }
-    return env->NewObjectArray(size, gStringClass, NULL);
-}
-
-static jintArray get_int_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
-    if (!grow) {
-        jintArray array = (jintArray)env->GetObjectField(obj, field);
-        if (array != NULL) {
-            return array;
-        }
-    }
-    return env->NewIntArray(size);
-}
-
-static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
-{
-    if (!grow) {
-        jlongArray array = (jlongArray)env->GetObjectField(obj, field);
-        if (array != NULL) {
-            return array;
-        }
-    }
-    return env->NewLongArray(size);
-}
-
-static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines,
-                                        const std::vector<std::string>& limitIfaces,
-                                        int limitTag, int limitUid, const char* path) {
-    FILE* fp = fopen(path, "re");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    int lastIdx = 1;
-    int idx;
-    char buffer[384];
-    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-        stats_line s;
-        int64_t rawTag;
-        char* pos = buffer;
-        char* endPos;
-        // First field is the index.
-        idx = (int)strtol(pos, &endPos, 10);
-        //ALOGI("Index #%d: %s", idx, buffer);
-        if (pos == endPos) {
-            // Skip lines that don't start with in index.  In particular,
-            // this will skip the initial header line.
-            continue;
-        }
-        if (idx != lastIdx + 1) {
-            ALOGE("inconsistent idx=%d after lastIdx=%d: %s", idx, lastIdx, buffer);
-            fclose(fp);
-            return -1;
-        }
-        lastIdx = idx;
-        pos = endPos;
-        // Skip whitespace.
-        while (*pos == ' ') {
-            pos++;
-        }
-        // Next field is iface.
-        int ifaceIdx = 0;
-        while (*pos != ' ' && *pos != 0 && ifaceIdx < (int)(sizeof(s.iface)-1)) {
-            s.iface[ifaceIdx] = *pos;
-            ifaceIdx++;
-            pos++;
-        }
-        if (*pos != ' ') {
-            ALOGE("bad iface: %s", buffer);
-            fclose(fp);
-            return -1;
-        }
-        s.iface[ifaceIdx] = 0;
-        if (limitIfaces.size() > 0) {
-            // Is this an iface the caller is interested in?
-            int i = 0;
-            while (i < (int)limitIfaces.size()) {
-                if (limitIfaces[i] == s.iface) {
-                    break;
-                }
-                i++;
-            }
-            if (i >= (int)limitIfaces.size()) {
-                // Nothing matched; skip this line.
-                //ALOGI("skipping due to iface: %s", buffer);
-                continue;
-            }
-        }
-
-        // Ignore whitespace
-        while (*pos == ' ') pos++;
-
-        // Find end of tag field
-        endPos = pos;
-        while (*endPos != ' ') endPos++;
-
-        // Three digit field is always 0x0, otherwise parse
-        if (endPos - pos == 3) {
-            rawTag = 0;
-        } else {
-            if (sscanf(pos, "%" PRIx64, &rawTag) != 1) {
-                ALOGE("bad tag: %s", pos);
-                fclose(fp);
-                return -1;
-            }
-        }
-        s.tag = rawTag >> 32;
-        if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
-            //ALOGI("skipping due to tag: %s", buffer);
-            continue;
-        }
-        pos = endPos;
-
-        // Ignore whitespace
-        while (*pos == ' ') pos++;
-
-        // Parse remaining fields.
-        if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
-                &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
-                &s.txBytes, &s.txPackets) == 6) {
-            if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
-                //ALOGI("skipping due to uid: %s", buffer);
-                continue;
-            }
-            lines->push_back(s);
-        } else {
-            //ALOGI("skipping due to bad remaining fields: %s", pos);
-        }
-    }
-
-    if (fclose(fp) != 0) {
-        ALOGE("Failed to close netstats file");
-        return -1;
-    }
-    return 0;
-}
-
-static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
-                            std::vector<stats_line>& lines) {
-    int size = lines.size();
-
-    bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
-
-    ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
-            gNetworkStatsClassInfo.iface, size, grow));
-    if (iface.get() == NULL) return -1;
-    ScopedIntArrayRW uid(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.uid, size, grow));
-    if (uid.get() == NULL) return -1;
-    ScopedIntArrayRW set(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.set, size, grow));
-    if (set.get() == NULL) return -1;
-    ScopedIntArrayRW tag(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.tag, size, grow));
-    if (tag.get() == NULL) return -1;
-    ScopedIntArrayRW metered(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.metered, size, grow));
-    if (metered.get() == NULL) return -1;
-    ScopedIntArrayRW roaming(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.roaming, size, grow));
-    if (roaming.get() == NULL) return -1;
-    ScopedIntArrayRW defaultNetwork(env, get_int_array(env, stats,
-            gNetworkStatsClassInfo.defaultNetwork, size, grow));
-    if (defaultNetwork.get() == NULL) return -1;
-    ScopedLongArrayRW rxBytes(env, get_long_array(env, stats,
-            gNetworkStatsClassInfo.rxBytes, size, grow));
-    if (rxBytes.get() == NULL) return -1;
-    ScopedLongArrayRW rxPackets(env, get_long_array(env, stats,
-            gNetworkStatsClassInfo.rxPackets, size, grow));
-    if (rxPackets.get() == NULL) return -1;
-    ScopedLongArrayRW txBytes(env, get_long_array(env, stats,
-            gNetworkStatsClassInfo.txBytes, size, grow));
-    if (txBytes.get() == NULL) return -1;
-    ScopedLongArrayRW txPackets(env, get_long_array(env, stats,
-            gNetworkStatsClassInfo.txPackets, size, grow));
-    if (txPackets.get() == NULL) return -1;
-    ScopedLongArrayRW operations(env, get_long_array(env, stats,
-            gNetworkStatsClassInfo.operations, size, grow));
-    if (operations.get() == NULL) return -1;
-
-    for (int i = 0; i < size; i++) {
-        ScopedLocalRef<jstring> ifaceString(env, env->NewStringUTF(lines[i].iface));
-        env->SetObjectArrayElement(iface.get(), i, ifaceString.get());
-
-        uid[i] = lines[i].uid;
-        set[i] = lines[i].set;
-        tag[i] = lines[i].tag;
-        // Metered, roaming and defaultNetwork are populated in Java-land.
-        rxBytes[i] = lines[i].rxBytes;
-        rxPackets[i] = lines[i].rxPackets;
-        txBytes[i] = lines[i].txBytes;
-        txPackets[i] = lines[i].txPackets;
-    }
-
-    env->SetIntField(stats, gNetworkStatsClassInfo.size, size);
-    if (grow) {
-        env->SetIntField(stats, gNetworkStatsClassInfo.capacity, size);
-        env->SetObjectField(stats, gNetworkStatsClassInfo.iface, iface.get());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.defaultNetwork,
-                defaultNetwork.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
-        env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
-    }
-    return 0;
-}
-
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
-                                  jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
-                                  jboolean useBpfStats) {
-
-    std::vector<std::string> limitIfaces;
-    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
-        int num = env->GetArrayLength(limitIfacesObj);
-        for (int i = 0; i < num; i++) {
-            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
-            ScopedUtfChars string8(env, string);
-            if (string8.c_str() != NULL) {
-                limitIfaces.push_back(std::string(string8.c_str()));
-            }
-        }
-    }
-    std::vector<stats_line> lines;
-
-
-    if (useBpfStats) {
-        if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
-            return -1;
-    } else {
-        ScopedUtfChars path8(env, path);
-        if (path8.c_str() == NULL) {
-            ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
-            return -1;
-        }
-        if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
-                                         limitUid, path8.c_str()) < 0)
-            return -1;
-    }
-
-    return statsLinesToNetworkStats(env, clazz, stats, lines);
-}
-
-static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) {
-    std::vector<stats_line> lines;
-
-    if (parseBpfNetworkStatsDev(&lines) < 0)
-            return -1;
-
-    return statsLinesToNetworkStats(env, clazz, stats, lines);
-}
-
-static const JNINativeMethod gMethods[] = {
-        { "nativeReadNetworkStatsDetail",
-                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
-                (void*) readNetworkStatsDetail },
-        { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
-                (void*) readNetworkStatsDev },
-};
-
-int register_android_server_net_NetworkStatsFactory(JNIEnv* env) {
-    int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods,
-            NELEM(gMethods));
-    gStringClass = env->FindClass("java/lang/String");
-    gStringClass = static_cast<jclass>(env->NewGlobalRef(gStringClass));
-
-    jclass clazz = env->FindClass("android/net/NetworkStats");
-    gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I");
-    gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I");
-    gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;");
-    gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I");
-    gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I");
-    gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I");
-    gNetworkStatsClassInfo.metered = env->GetFieldID(clazz, "metered", "[I");
-    gNetworkStatsClassInfo.roaming = env->GetFieldID(clazz, "roaming", "[I");
-    gNetworkStatsClassInfo.defaultNetwork = env->GetFieldID(clazz, "defaultNetwork", "[I");
-    gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J");
-    gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J");
-    gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J");
-    gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J");
-    gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J");
-
-    return err;
-}
-
-}
diff --git a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
deleted file mode 100644
index 39cbaf7..0000000
--- a/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed 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.
- */
-
-#define LOG_TAG "NetworkStatsNative"
-
-#include <cutils/qtaguid.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <jni.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "bpf/BpfUtils.h"
-#include "netdbpf/BpfNetworkStats.h"
-
-using android::bpf::bpfGetUidStats;
-using android::bpf::bpfGetIfaceStats;
-
-namespace android {
-
-// NOTE: keep these in sync with TrafficStats.java
-static const uint64_t UNKNOWN = -1;
-
-enum StatsType {
-    RX_BYTES = 0,
-    RX_PACKETS = 1,
-    TX_BYTES = 2,
-    TX_PACKETS = 3,
-    TCP_RX_PACKETS = 4,
-    TCP_TX_PACKETS = 5
-};
-
-static uint64_t getStatsType(Stats* stats, StatsType type) {
-    switch (type) {
-        case RX_BYTES:
-            return stats->rxBytes;
-        case RX_PACKETS:
-            return stats->rxPackets;
-        case TX_BYTES:
-            return stats->txBytes;
-        case TX_PACKETS:
-            return stats->txPackets;
-        case TCP_RX_PACKETS:
-            return stats->tcpRxPackets;
-        case TCP_TX_PACKETS:
-            return stats->tcpTxPackets;
-        default:
-            return UNKNOWN;
-    }
-}
-
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
-    Stats stats = {};
-
-    if (bpfGetIfaceStats(NULL, &stats) == 0) {
-        return getStatsType(&stats, (StatsType) type);
-    } else {
-        return UNKNOWN;
-    }
-}
-
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
-    ScopedUtfChars iface8(env, iface);
-    if (iface8.c_str() == NULL) {
-        return UNKNOWN;
-    }
-
-    Stats stats = {};
-
-    if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
-        return getStatsType(&stats, (StatsType) type);
-    } else {
-        return UNKNOWN;
-    }
-}
-
-static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
-    Stats stats = {};
-
-    if (bpfGetUidStats(uid, &stats) == 0) {
-        return getStatsType(&stats, (StatsType) type);
-    } else {
-        return UNKNOWN;
-    }
-}
-
-static const JNINativeMethod gMethods[] = {
-        {"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
-        {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
-        {"nativeGetUidStat", "(II)J", (void*)getUidStat},
-};
-
-int register_android_server_net_NetworkStatsService(JNIEnv* env) {
-    return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods,
-                                    NELEM(gMethods));
-}
-
-}
diff --git a/packages/ConnectivityT/service/jni/onload.cpp b/packages/ConnectivityT/service/jni/onload.cpp
deleted file mode 100644
index bca4697..0000000
--- a/packages/ConnectivityT/service/jni/onload.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-#include <nativehelper/JNIHelp.h>
-#include <log/log.h>
-
-namespace android {
-
-int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
-
-extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
-    JNIEnv *env;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        ALOGE("GetEnv failed");
-        return JNI_ERR;
-    }
-
-    if (register_com_android_net_module_util_BpfMap(env,
-            "com/android/net/module/util/BpfMap") < 0) return JNI_ERR;
-
-    return JNI_VERSION_1_6;
-}
-
-};
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java b/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
deleted file mode 100644
index 0cf9dcd..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
+++ /dev/null
@@ -1,25 +0,0 @@
-
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-interface INativeDaemonConnectorCallbacks {
-
-    void onDaemonConnected();
-    boolean onCheckHoldWakeLock(int code);
-    boolean onEvent(int code, String raw, String[] cooked);
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
deleted file mode 100644
index 4bc40ea..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
+++ /dev/null
@@ -1,1878 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static android.Manifest.permission.DUMP;
-import static android.net.IpSecManager.INVALID_RESOURCE_ID;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_UNSPEC;
-import static android.system.OsConstants.EINVAL;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.SOCK_DGRAM;
-
-import android.annotation.NonNull;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.IIpSecService;
-import android.net.INetd;
-import android.net.InetAddresses;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecConfig;
-import android.net.IpSecManager;
-import android.net.IpSecSpiResponse;
-import android.net.IpSecTransform;
-import android.net.IpSecTransformResponse;
-import android.net.IpSecTunnelInterfaceResponse;
-import android.net.IpSecUdpEncapResponse;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.TrafficStats;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Range;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-import com.android.net.module.util.BinderUtils;
-import com.android.net.module.util.NetdUtils;
-import com.android.net.module.util.PermissionUtils;
-
-import libcore.io.IoUtils;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A service to manage multiple clients that want to access the IpSec API. The service is
- * responsible for maintaining a list of clients and managing the resources (and related quotas)
- * that each of them own.
- *
- * <p>Synchronization in IpSecService is done on all entrypoints due to potential race conditions at
- * the kernel/xfrm level. Further, this allows the simplifying assumption to be made that only one
- * thread is ever running at a time.
- *
- * @hide
- */
-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 int[] ADDRESS_FAMILIES =
-            new int[] {OsConstants.AF_INET, OsConstants.AF_INET6};
-
-    private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms
-    private static final InetAddress INADDR_ANY;
-
-    @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});
-        } catch (UnknownHostException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved
-    static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer
-
-    /* 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
-     * kernel data structures. Accessing this variable is not thread safe, so it is only read or
-     * modified within blocks synchronized on IpSecService.this. We want to avoid -1
-     * (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it).
-     */
-    @GuardedBy("IpSecService.this")
-    private int mNextResourceId = 1;
-
-    /**
-     * 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;
-        }
-    }
-
-    final UidFdTagger mUidFdTagger;
-
-    /**
-     * Interface for user-reference and kernel-resource cleanup.
-     *
-     * <p>This interface must be implemented for a resource to be reference counted.
-     */
-    @VisibleForTesting
-    public interface IResource {
-        /**
-         * Invalidates a IResource object, ensuring it is invalid for the purposes of allocating new
-         * objects dependent on it.
-         *
-         * <p>Implementations of this method are expected to remove references to the IResource
-         * object from the IpSecService's tracking arrays. The removal from the arrays ensures that
-         * the resource is considered invalid for user access or allocation or use in other
-         * resources.
-         *
-         * <p>References to the IResource object may be held by other RefcountedResource objects,
-         * and as such, the underlying resources and quota may not be cleaned up.
-         */
-        void invalidate() throws RemoteException;
-
-        /**
-         * Releases underlying resources and related quotas.
-         *
-         * <p>Implementations of this method are expected to remove all system resources that are
-         * tracked by the IResource object. Due to other RefcountedResource objects potentially
-         * having references to the IResource object, freeUnderlyingResources may not always be
-         * called from releaseIfUnreferencedRecursively().
-         */
-        void freeUnderlyingResources() throws RemoteException;
-    }
-
-    /**
-     * RefcountedResource manages references and dependencies in an exclusively acyclic graph.
-     *
-     * <p>RefcountedResource implements both explicit and implicit resource management. Creating a
-     * RefcountedResource object creates an explicit reference that must be freed by calling
-     * userRelease(). Additionally, adding this object as a child of another RefcountedResource
-     * object will add an implicit reference.
-     *
-     * <p>Resources are cleaned up when all references, both implicit and explicit, are released
-     * (ie, when userRelease() is called and when all parents have called releaseReference() on this
-     * object.)
-     */
-    @VisibleForTesting
-    public class RefcountedResource<T extends IResource> implements IBinder.DeathRecipient {
-        private final T mResource;
-        private final List<RefcountedResource> mChildren;
-        int mRefCount = 1; // starts at 1 for user's reference.
-        IBinder mBinder;
-
-        RefcountedResource(T resource, IBinder binder, RefcountedResource... children) {
-            synchronized (IpSecService.this) {
-                this.mResource = resource;
-                this.mChildren = new ArrayList<>(children.length);
-                this.mBinder = binder;
-
-                for (RefcountedResource child : children) {
-                    mChildren.add(child);
-                    child.mRefCount++;
-                }
-
-                try {
-                    mBinder.linkToDeath(this, 0);
-                } catch (RemoteException e) {
-                    binderDied();
-                    e.rethrowFromSystemServer();
-                }
-            }
-        }
-
-        /**
-         * If the Binder object dies, this function is called to free the system resources that are
-         * being tracked by this record and to subsequently release this record for garbage
-         * collection
-         */
-        @Override
-        public void binderDied() {
-            synchronized (IpSecService.this) {
-                try {
-                    userRelease();
-                } catch (Exception e) {
-                    Log.e(TAG, "Failed to release resource: " + e);
-                }
-            }
-        }
-
-        public T getResource() {
-            return mResource;
-        }
-
-        /**
-         * Unlinks from binder and performs IpSecService resource cleanup (removes from resource
-         * arrays)
-         *
-         * <p>If this method has been previously called, the RefcountedResource's binder field will
-         * be null, and the method will return without performing the cleanup a second time.
-         *
-         * <p>Note that calling this function does not imply that kernel resources will be freed at
-         * this time, or that the related quota will be returned. Such actions will only be
-         * performed upon the reference count reaching zero.
-         */
-        @GuardedBy("IpSecService.this")
-        public void userRelease() throws RemoteException {
-            // Prevent users from putting reference counts into a bad state by calling
-            // userRelease() multiple times.
-            if (mBinder == null) {
-                return;
-            }
-
-            mBinder.unlinkToDeath(this, 0);
-            mBinder = null;
-
-            mResource.invalidate();
-
-            releaseReference();
-        }
-
-        /**
-         * Removes a reference to this resource. If the resultant reference count is zero, the
-         * underlying resources are freed, and references to all child resources are also dropped
-         * recursively (resulting in them freeing their resources and children, etcetera)
-         *
-         * <p>This method also sets the reference count to an invalid value (-1) to signify that it
-         * has been fully released. Any subsequent calls to this method will result in an
-         * IllegalStateException being thrown due to resource already having been previously
-         * released
-         */
-        @VisibleForTesting
-        @GuardedBy("IpSecService.this")
-        public void releaseReference() throws RemoteException {
-            mRefCount--;
-
-            if (mRefCount > 0) {
-                return;
-            } else if (mRefCount < 0) {
-                throw new IllegalStateException(
-                        "Invalid operation - resource has already been released.");
-            }
-
-            // Cleanup own resources
-            mResource.freeUnderlyingResources();
-
-            // Cleanup child resources as needed
-            for (RefcountedResource<? extends IResource> child : mChildren) {
-                child.releaseReference();
-            }
-
-            // Enforce that resource cleanup can only be called once
-            // By decrementing the refcount (from 0 to -1), the next call will throw an
-            // IllegalStateException - it has already been released fully.
-            mRefCount--;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{mResource=")
-                    .append(mResource)
-                    .append(", mRefCount=")
-                    .append(mRefCount)
-                    .append(", mChildren=")
-                    .append(mChildren)
-                    .append("}")
-                    .toString();
-        }
-    }
-
-    /**
-     * Very simple counting class that looks much like a counting semaphore
-     *
-     * <p>This class is not thread-safe, and expects that that users of this class will ensure
-     * synchronization and thread safety by holding the IpSecService.this instance lock.
-     */
-    @VisibleForTesting
-    static class ResourceTracker {
-        private final int mMax;
-        int mCurrent;
-
-        ResourceTracker(int max) {
-            mMax = max;
-            mCurrent = 0;
-        }
-
-        boolean isAvailable() {
-            return (mCurrent < mMax);
-        }
-
-        void take() {
-            if (!isAvailable()) {
-                Log.wtf(TAG, "Too many resources allocated!");
-            }
-            mCurrent++;
-        }
-
-        void give() {
-            if (mCurrent <= 0) {
-                Log.wtf(TAG, "We've released this resource too many times");
-            }
-            mCurrent--;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{mCurrent=")
-                    .append(mCurrent)
-                    .append(", mMax=")
-                    .append(mMax)
-                    .append("}")
-                    .toString();
-        }
-    }
-
-    @VisibleForTesting
-    static final class UserRecord {
-        /* Maximum number of each type of resource that a single UID may possess */
-
-        // Up to 4 active VPNs/IWLAN with potential soft handover.
-        public static final int MAX_NUM_TUNNEL_INTERFACES = 8;
-        public static final int MAX_NUM_ENCAP_SOCKETS = 16;
-
-        // SPIs and Transforms are both cheap, and are 1:1 correlated.
-        public static final int MAX_NUM_TRANSFORMS = 64;
-        public static final int MAX_NUM_SPIS = 64;
-
-        /**
-         * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing
-         * and explicit (user) reference management.
-         *
-         * <p>These are stored in separate arrays to improve debuggability and dump output clarity.
-         *
-         * <p>Resources are removed from this array when the user releases their explicit reference
-         * by calling one of the releaseResource() methods.
-         */
-        final RefcountedResourceArray<SpiRecord> mSpiRecords =
-                new RefcountedResourceArray<>(SpiRecord.class.getSimpleName());
-        final RefcountedResourceArray<TransformRecord> mTransformRecords =
-                new RefcountedResourceArray<>(TransformRecord.class.getSimpleName());
-        final RefcountedResourceArray<EncapSocketRecord> mEncapSocketRecords =
-                new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName());
-        final RefcountedResourceArray<TunnelInterfaceRecord> mTunnelInterfaceRecords =
-                new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName());
-
-        /**
-         * Trackers for quotas for each of the OwnedResource types.
-         *
-         * <p>These trackers are separate from the resource arrays, since they are incremented and
-         * decremented at different points in time. Specifically, quota is only returned upon final
-         * resource deallocation (after all explicit and implicit references are released). Note
-         * that it is possible that calls to releaseResource() will not return the used quota if
-         * there are other resources that depend on (are parents of) the resource being released.
-         */
-        final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS);
-        final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS);
-        final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS);
-        final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES);
-
-        void removeSpiRecord(int resourceId) {
-            mSpiRecords.remove(resourceId);
-        }
-
-        void removeTransformRecord(int resourceId) {
-            mTransformRecords.remove(resourceId);
-        }
-
-        void removeTunnelInterfaceRecord(int resourceId) {
-            mTunnelInterfaceRecords.remove(resourceId);
-        }
-
-        void removeEncapSocketRecord(int resourceId) {
-            mEncapSocketRecords.remove(resourceId);
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{mSpiQuotaTracker=")
-                    .append(mSpiQuotaTracker)
-                    .append(", mTransformQuotaTracker=")
-                    .append(mTransformQuotaTracker)
-                    .append(", mSocketQuotaTracker=")
-                    .append(mSocketQuotaTracker)
-                    .append(", mTunnelQuotaTracker=")
-                    .append(mTunnelQuotaTracker)
-                    .append(", mSpiRecords=")
-                    .append(mSpiRecords)
-                    .append(", mTransformRecords=")
-                    .append(mTransformRecords)
-                    .append(", mEncapSocketRecords=")
-                    .append(mEncapSocketRecords)
-                    .append(", mTunnelInterfaceRecords=")
-                    .append(mTunnelInterfaceRecords)
-                    .append("}")
-                    .toString();
-        }
-    }
-
-    /**
-     * This class is not thread-safe, and expects that that users of this class will ensure
-     * synchronization and thread safety by holding the IpSecService.this instance lock.
-     */
-    @VisibleForTesting
-    static final class UserResourceTracker {
-        private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
-
-        /** Lazy-initialization/getter that populates or retrieves the UserRecord as needed */
-        public UserRecord getUserRecord(int uid) {
-            checkCallerUid(uid);
-
-            UserRecord r = mUserRecords.get(uid);
-            if (r == null) {
-                r = new UserRecord();
-                mUserRecords.put(uid, r);
-            }
-            return r;
-        }
-
-        /** Safety method; guards against access of other user's UserRecords */
-        private void checkCallerUid(int uid) {
-            if (uid != Binder.getCallingUid() && Process.SYSTEM_UID != Binder.getCallingUid()) {
-                throw new SecurityException("Attempted access of unowned resources");
-            }
-        }
-
-        @Override
-        public String toString() {
-            return mUserRecords.toString();
-        }
-    }
-
-    @VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker();
-
-    /**
-     * The OwnedResourceRecord class provides a facility to cleanly and reliably track system
-     * resources. It relies on a provided resourceId that should uniquely identify the kernel
-     * resource. To use this class, the user should implement the invalidate() and
-     * freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource
-     * tracking arrays and kernel resources, respectively.
-     *
-     * <p>This class associates kernel resources with the UID that owns and controls them.
-     */
-    private abstract class OwnedResourceRecord implements IResource {
-        final int mPid;
-        final int mUid;
-        protected final int mResourceId;
-
-        OwnedResourceRecord(int resourceId) {
-            super();
-            if (resourceId == INVALID_RESOURCE_ID) {
-                throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID");
-            }
-            mResourceId = resourceId;
-            mPid = Binder.getCallingPid();
-            mUid = Binder.getCallingUid();
-
-            getResourceTracker().take();
-        }
-
-        @Override
-        public abstract void invalidate() throws RemoteException;
-
-        /** Convenience method; retrieves the user resource record for the stored UID. */
-        protected UserRecord getUserRecord() {
-            return mUserResourceTracker.getUserRecord(mUid);
-        }
-
-        @Override
-        public abstract void freeUnderlyingResources() throws RemoteException;
-
-        /** Get the resource tracker for this resource */
-        protected abstract ResourceTracker getResourceTracker();
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{mResourceId=")
-                    .append(mResourceId)
-                    .append(", pid=")
-                    .append(mPid)
-                    .append(", uid=")
-                    .append(mUid)
-                    .append("}")
-                    .toString();
-        }
-    };
-
-    /**
-     * Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing.
-     *
-     * <p>RefcountedResourceArray prevents null insertions, and throws an IllegalArgumentException
-     * if a key is not found during a retrieval process.
-     */
-    static class RefcountedResourceArray<T extends IResource> {
-        SparseArray<RefcountedResource<T>> mArray = new SparseArray<>();
-        private final String mTypeName;
-
-        RefcountedResourceArray(String typeName) {
-            this.mTypeName = typeName;
-        }
-
-        /**
-         * Accessor method to get inner resource object.
-         *
-         * @throws IllegalArgumentException if no resource with provided key is found.
-         */
-        T getResourceOrThrow(int key) {
-            return getRefcountedResourceOrThrow(key).getResource();
-        }
-
-        /**
-         * Accessor method to get reference counting wrapper.
-         *
-         * @throws IllegalArgumentException if no resource with provided key is found.
-         */
-        RefcountedResource<T> getRefcountedResourceOrThrow(int key) {
-            RefcountedResource<T> resource = mArray.get(key);
-            if (resource == null) {
-                throw new IllegalArgumentException(
-                        String.format("No such %s found for given id: %d", mTypeName, key));
-            }
-
-            return resource;
-        }
-
-        void put(int key, RefcountedResource<T> obj) {
-            Objects.requireNonNull(obj, "Null resources cannot be added");
-            mArray.put(key, obj);
-        }
-
-        void remove(int key) {
-            mArray.remove(key);
-        }
-
-        @Override
-        public String toString() {
-            return mArray.toString();
-        }
-    }
-
-    /**
-     * Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is
-     * created, the SpiRecord that originally tracked the SAs will reliquish the
-     * responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag.
-     */
-    private final class TransformRecord extends OwnedResourceRecord {
-        private final IpSecConfig mConfig;
-        private final SpiRecord mSpi;
-        private final EncapSocketRecord mSocket;
-
-        TransformRecord(
-                int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) {
-            super(resourceId);
-            mConfig = config;
-            mSpi = spi;
-            mSocket = socket;
-
-            spi.setOwnedByTransform();
-        }
-
-        public IpSecConfig getConfig() {
-            return mConfig;
-        }
-
-        public SpiRecord getSpiRecord() {
-            return mSpi;
-        }
-
-        public EncapSocketRecord getSocketRecord() {
-            return mSocket;
-        }
-
-        /** always guarded by IpSecService#this */
-        @Override
-        public void freeUnderlyingResources() {
-            int spi = mSpi.getSpi();
-            try {
-                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);
-            }
-
-            getResourceTracker().give();
-        }
-
-        @Override
-        public void invalidate() throws RemoteException {
-            getUserRecord().removeTransformRecord(mResourceId);
-        }
-
-        @Override
-        protected ResourceTracker getResourceTracker() {
-            return getUserRecord().mTransformQuotaTracker;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder strBuilder = new StringBuilder();
-            strBuilder
-                    .append("{super=")
-                    .append(super.toString())
-                    .append(", mSocket=")
-                    .append(mSocket)
-                    .append(", mSpi.mResourceId=")
-                    .append(mSpi.mResourceId)
-                    .append(", mConfig=")
-                    .append(mConfig)
-                    .append("}");
-            return strBuilder.toString();
-        }
-    }
-
-    /**
-     * Tracks a single SA in the kernel, and manages cleanup paths. Once used in a Transform, the
-     * responsibility for cleaning up underlying resources will be passed to the TransformRecord
-     * object
-     */
-    private final class SpiRecord extends OwnedResourceRecord {
-        private final String mSourceAddress;
-        private final String mDestinationAddress;
-        private int mSpi;
-
-        private boolean mOwnedByTransform = false;
-
-        SpiRecord(int resourceId, String sourceAddress,
-                String destinationAddress, int spi) {
-            super(resourceId);
-            mSourceAddress = sourceAddress;
-            mDestinationAddress = destinationAddress;
-            mSpi = spi;
-        }
-
-        /** always guarded by IpSecService#this */
-        @Override
-        public void freeUnderlyingResources() {
-            try {
-                if (!mOwnedByTransform) {
-                    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);
-            }
-
-            mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-
-            getResourceTracker().give();
-        }
-
-        public int getSpi() {
-            return mSpi;
-        }
-
-        public String getDestinationAddress() {
-            return mDestinationAddress;
-        }
-
-        public void setOwnedByTransform() {
-            if (mOwnedByTransform) {
-                // Programming error
-                throw new IllegalStateException("Cannot own an SPI twice!");
-            }
-
-            mOwnedByTransform = true;
-        }
-
-        public boolean getOwnedByTransform() {
-            return mOwnedByTransform;
-        }
-
-        @Override
-        public void invalidate() throws RemoteException {
-            getUserRecord().removeSpiRecord(mResourceId);
-        }
-
-        @Override
-        protected ResourceTracker getResourceTracker() {
-            return getUserRecord().mSpiQuotaTracker;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder strBuilder = new StringBuilder();
-            strBuilder
-                    .append("{super=")
-                    .append(super.toString())
-                    .append(", mSpi=")
-                    .append(mSpi)
-                    .append(", mSourceAddress=")
-                    .append(mSourceAddress)
-                    .append(", mDestinationAddress=")
-                    .append(mDestinationAddress)
-                    .append(", mOwnedByTransform=")
-                    .append(mOwnedByTransform)
-                    .append("}");
-            return strBuilder.toString();
-        }
-    }
-
-    private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray();
-    final Range<Integer> mNetIdRange = ConnectivityManager.getIpSecNetIdRange();
-    private int mNextTunnelNetId = mNetIdRange.getLower();
-
-    /**
-     * Reserves a netId within the range of netIds allocated for IPsec tunnel interfaces
-     *
-     * <p>This method should only be called from Binder threads. Do not call this from within the
-     * system server as it will crash the system on failure.
-     *
-     * @return an integer key within the netId range, if successful
-     * @throws IllegalStateException if unsuccessful (all netId are currently reserved)
-     */
-    @VisibleForTesting
-    int reserveNetId() {
-        final int range = mNetIdRange.getUpper() - mNetIdRange.getLower() + 1;
-        synchronized (mTunnelNetIds) {
-            for (int i = 0; i < range; i++) {
-                final int netId = mNextTunnelNetId;
-                if (++mNextTunnelNetId > mNetIdRange.getUpper()) {
-                    mNextTunnelNetId = mNetIdRange.getLower();
-                }
-                if (!mTunnelNetIds.get(netId)) {
-                    mTunnelNetIds.put(netId, true);
-                    return netId;
-                }
-            }
-        }
-        throw new IllegalStateException("No free netIds to allocate");
-    }
-
-    @VisibleForTesting
-    void releaseNetId(int netId) {
-        synchronized (mTunnelNetIds) {
-            mTunnelNetIds.delete(netId);
-        }
-    }
-
-    /**
-     * Tracks an tunnel interface, and manages cleanup paths.
-     *
-     * <p>This class is not thread-safe, and expects that that users of this class will ensure
-     * synchronization and thread safety by holding the IpSecService.this instance lock
-     */
-    @VisibleForTesting
-    final class TunnelInterfaceRecord extends OwnedResourceRecord {
-        private final String mInterfaceName;
-
-        // outer addresses
-        private final String mLocalAddress;
-        private final String mRemoteAddress;
-
-        private final int mIkey;
-        private final int mOkey;
-
-        private final int mIfId;
-
-        private Network mUnderlyingNetwork;
-
-        TunnelInterfaceRecord(
-                int resourceId,
-                String interfaceName,
-                Network underlyingNetwork,
-                String localAddr,
-                String remoteAddr,
-                int ikey,
-                int okey,
-                int intfId) {
-            super(resourceId);
-
-            mInterfaceName = interfaceName;
-            mUnderlyingNetwork = underlyingNetwork;
-            mLocalAddress = localAddr;
-            mRemoteAddress = remoteAddr;
-            mIkey = ikey;
-            mOkey = okey;
-            mIfId = intfId;
-        }
-
-        /** always guarded by IpSecService#this */
-        @Override
-        public void freeUnderlyingResources() {
-            // Calls to netd
-            //       Teardown VTI
-            //       Delete global policies
-            try {
-                mNetd.ipSecRemoveTunnelInterface(mInterfaceName);
-
-                for (int selAddrFamily : ADDRESS_FAMILIES) {
-                    mNetd.ipSecDeleteSecurityPolicy(
-                            mUid,
-                            selAddrFamily,
-                            IpSecManager.DIRECTION_OUT,
-                            mOkey,
-                            0xffffffff,
-                            mIfId);
-                    mNetd.ipSecDeleteSecurityPolicy(
-                            mUid,
-                            selAddrFamily,
-                            IpSecManager.DIRECTION_IN,
-                            mIkey,
-                            0xffffffff,
-                            mIfId);
-                }
-            } catch (ServiceSpecificException | RemoteException e) {
-                Log.e(
-                        TAG,
-                        "Failed to delete VTI with interface name: "
-                                + mInterfaceName
-                                + " and id: "
-                                + mResourceId, e);
-            }
-
-            getResourceTracker().give();
-            releaseNetId(mIkey);
-            releaseNetId(mOkey);
-        }
-
-        @GuardedBy("IpSecService.this")
-        public void setUnderlyingNetwork(Network underlyingNetwork) {
-            // When #applyTunnelModeTransform is called, this new underlying network will be used to
-            // update the output mark of the input transform.
-            mUnderlyingNetwork = underlyingNetwork;
-        }
-
-        @GuardedBy("IpSecService.this")
-        public Network getUnderlyingNetwork() {
-            return mUnderlyingNetwork;
-        }
-
-        public String getInterfaceName() {
-            return mInterfaceName;
-        }
-
-        /** Returns the local, outer address for the tunnelInterface */
-        public String getLocalAddress() {
-            return mLocalAddress;
-        }
-
-        /** Returns the remote, outer address for the tunnelInterface */
-        public String getRemoteAddress() {
-            return mRemoteAddress;
-        }
-
-        public int getIkey() {
-            return mIkey;
-        }
-
-        public int getOkey() {
-            return mOkey;
-        }
-
-        public int getIfId() {
-            return mIfId;
-        }
-
-        @Override
-        protected ResourceTracker getResourceTracker() {
-            return getUserRecord().mTunnelQuotaTracker;
-        }
-
-        @Override
-        public void invalidate() {
-            getUserRecord().removeTunnelInterfaceRecord(mResourceId);
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{super=")
-                    .append(super.toString())
-                    .append(", mInterfaceName=")
-                    .append(mInterfaceName)
-                    .append(", mUnderlyingNetwork=")
-                    .append(mUnderlyingNetwork)
-                    .append(", mLocalAddress=")
-                    .append(mLocalAddress)
-                    .append(", mRemoteAddress=")
-                    .append(mRemoteAddress)
-                    .append(", mIkey=")
-                    .append(mIkey)
-                    .append(", mOkey=")
-                    .append(mOkey)
-                    .append("}")
-                    .toString();
-        }
-    }
-
-    /**
-     * Tracks a UDP encap socket, and manages cleanup paths
-     *
-     * <p>While this class does not manage non-kernel resources, race conditions around socket
-     * binding require that the service creates the encap socket, binds it and applies the socket
-     * policy before handing it to a user.
-     */
-    private final class EncapSocketRecord extends OwnedResourceRecord {
-        private FileDescriptor mSocket;
-        private final int mPort;
-
-        EncapSocketRecord(int resourceId, FileDescriptor socket, int port) {
-            super(resourceId);
-            mSocket = socket;
-            mPort = port;
-        }
-
-        /** always guarded by IpSecService#this */
-        @Override
-        public void freeUnderlyingResources() {
-            Log.d(TAG, "Closing port " + mPort);
-            IoUtils.closeQuietly(mSocket);
-            mSocket = null;
-
-            getResourceTracker().give();
-        }
-
-        public int getPort() {
-            return mPort;
-        }
-
-        public FileDescriptor getFileDescriptor() {
-            return mSocket;
-        }
-
-        @Override
-        protected ResourceTracker getResourceTracker() {
-            return getUserRecord().mSocketQuotaTracker;
-        }
-
-        @Override
-        public void invalidate() {
-            getUserRecord().removeEncapSocketRecord(mResourceId);
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder()
-                    .append("{super=")
-                    .append(super.toString())
-                    .append(", mSocket=")
-                    .append(mSocket)
-                    .append(", mPort=")
-                    .append(mPort)
-                    .append("}")
-                    .toString();
-        }
-    }
-
-    /**
-     * Constructs a new IpSecService instance
-     *
-     * @param context Binder context for this service
-     */
-    public IpSecService(Context context) {
-        this(context, new Dependencies());
-    }
-
-    @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");
-        return appOps;
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public IpSecService(Context context, Dependencies deps) {
-        this(
-                context,
-                deps,
-                (fd, uid) -> {
-                    try {
-                        TrafficStats.setThreadStatsUid(uid);
-                        TrafficStats.tagFileDescriptor(fd);
-                    } finally {
-                        TrafficStats.clearThreadStatsUid();
-                    }
-                });
-    }
-
-    /** @hide */
-    @VisibleForTesting
-    public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) {
-        mContext = context;
-        mDeps = Objects.requireNonNull(deps, "Missing dependencies.");
-        mUidFdTagger = uidFdTagger;
-        try {
-            mNetd = mDeps.getNetdInstance(mContext);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
-     * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
-     */
-    private static void checkInetAddress(String inetAddress) {
-        if (TextUtils.isEmpty(inetAddress)) {
-            throw new IllegalArgumentException("Unspecified address");
-        }
-
-        InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress);
-
-        if (checkAddr.isAnyLocalAddress()) {
-            throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
-        }
-    }
-
-    /**
-     * Checks the user-provided direction field and throws an IllegalArgumentException if it is not
-     * DIRECTION_IN or DIRECTION_OUT
-     */
-    private void checkDirection(int direction) {
-        switch (direction) {
-            case IpSecManager.DIRECTION_OUT:
-            case IpSecManager.DIRECTION_IN:
-                return;
-            case IpSecManager.DIRECTION_FWD:
-                // Only NETWORK_STACK or MAINLINE_NETWORK_STACK allowed to use forward policies
-                PermissionUtils.enforceNetworkStackPermission(mContext);
-                return;
-        }
-        throw new IllegalArgumentException("Invalid Direction: " + direction);
-    }
-
-    /** Get a new SPI and maintain the reservation in the system server */
-    @Override
-    public synchronized IpSecSpiResponse allocateSecurityParameterIndex(
-            String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException {
-        checkInetAddress(destinationAddress);
-        // RFC 4303 Section 2.1 - 0=local, 1-255=reserved.
-        if (requestedSpi > 0 && requestedSpi < 256) {
-            throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255.");
-        }
-        Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
-
-        int callingUid = Binder.getCallingUid();
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
-        final int resourceId = mNextResourceId++;
-
-        int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-        try {
-            if (!userRecord.mSpiQuotaTracker.isAvailable()) {
-                return new IpSecSpiResponse(
-                        IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
-            }
-
-            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));
-        } catch (ServiceSpecificException e) {
-            if (e.errorCode == OsConstants.ENOENT) {
-                return new IpSecSpiResponse(
-                        IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
-            }
-            throw e;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-        return new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, spi);
-    }
-
-    /* This method should only be called from Binder threads. Do not call this from
-     * within the system server as it will crash the system on failure.
-     */
-    private void releaseResource(RefcountedResourceArray resArray, int resourceId)
-            throws RemoteException {
-        resArray.getRefcountedResourceOrThrow(resourceId).userRelease();
-    }
-
-    /** Release a previously allocated SPI that has been registered with the system server */
-    @Override
-    public synchronized void releaseSecurityParameterIndex(int resourceId) throws RemoteException {
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        releaseResource(userRecord.mSpiRecords, resourceId);
-    }
-
-    /**
-     * This function finds and forcibly binds to a random system port, ensuring that the port cannot
-     * be unbound.
-     *
-     * <p>A socket cannot be un-bound from a port if it was bound to that port by number. To select
-     * a random open port and then bind by number, this function creates a temp socket, binds to a
-     * random port (specifying 0), gets that port number, and then uses is to bind the user's UDP
-     * Encapsulation Socket forcibly, so that it cannot be un-bound by the user with the returned
-     * FileHandle.
-     *
-     * <p>The loop in this function handles the inherent race window between un-binding to a port
-     * and re-binding, during which the system could *technically* hand that port out to someone
-     * else.
-     */
-    private int bindToRandomPort(FileDescriptor sockFd) throws IOException {
-        for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) {
-            try {
-                FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-                Os.bind(probeSocket, INADDR_ANY, 0);
-                int port = ((InetSocketAddress) Os.getsockname(probeSocket)).getPort();
-                Os.close(probeSocket);
-                Log.v(TAG, "Binding to port " + port);
-                Os.bind(sockFd, INADDR_ANY, port);
-                return port;
-            } catch (ErrnoException e) {
-                // Someone miraculously claimed the port just after we closed probeSocket.
-                if (e.errno == OsConstants.EADDRINUSE) {
-                    continue;
-                }
-                throw e.rethrowAsIOException();
-            }
-        }
-        throw new IOException("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port");
-    }
-
-    /**
-     * Functional interface to do traffic tagging of given sockets to UIDs.
-     *
-     * <p>Specifically used by openUdpEncapsulationSocket to ensure data usage on the UDP encap
-     * sockets are billed to the UID that the UDP encap socket was created on behalf of.
-     *
-     * <p>Separate class so that the socket tagging logic can be mocked; TrafficStats uses static
-     * methods that cannot be easily mocked/tested.
-     */
-    @VisibleForTesting
-    public interface UidFdTagger {
-        /**
-         * Sets socket tag to assign all traffic to the provided UID.
-         *
-         * <p>Since the socket is created on behalf of an unprivileged application, all traffic
-         * should be accounted to the UID of the unprivileged application.
-         */
-        void tag(FileDescriptor fd, int uid) throws IOException;
-    }
-
-    /**
-     * Open a socket via the system server and bind it to the specified port (random if port=0).
-     * This will return a PFD to the user that represent a bound UDP socket. The system server will
-     * cache the socket and a record of its owner so that it can and must be freed when no longer
-     * needed.
-     */
-    @Override
-    public synchronized IpSecUdpEncapResponse openUdpEncapsulationSocket(int port, IBinder binder)
-            throws RemoteException {
-        if (port != 0 && (port < FREE_PORT_MIN || port > PORT_MAX)) {
-            throw new IllegalArgumentException(
-                    "Specified port number must be a valid non-reserved UDP port");
-        }
-        Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
-
-        int callingUid = Binder.getCallingUid();
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
-        final int resourceId = mNextResourceId++;
-
-        ParcelFileDescriptor pFd = null;
-        try {
-            if (!userRecord.mSocketQuotaTracker.isAvailable()) {
-                return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
-            }
-
-            FileDescriptor sockFd = null;
-            try {
-                sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-                pFd = ParcelFileDescriptor.dup(sockFd);
-            } finally {
-                IoUtils.closeQuietly(sockFd);
-            }
-
-            mUidFdTagger.tag(pFd.getFileDescriptor(), callingUid);
-            // This code is common to both the unspecified and specified port cases
-            Os.setsockoptInt(
-                    pFd.getFileDescriptor(),
-                    OsConstants.IPPROTO_UDP,
-                    OsConstants.UDP_ENCAP,
-                    OsConstants.UDP_ENCAP_ESPINUDP);
-
-            mNetd.ipSecSetEncapSocketOwner(pFd, callingUid);
-            if (port != 0) {
-                Log.v(TAG, "Binding to port " + port);
-                Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port);
-            } else {
-                port = bindToRandomPort(pFd.getFileDescriptor());
-            }
-
-            userRecord.mEncapSocketRecords.put(
-                    resourceId,
-                    new RefcountedResource<EncapSocketRecord>(
-                            new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port),
-                            binder));
-            return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port,
-                    pFd.getFileDescriptor());
-        } catch (IOException | ErrnoException e) {
-            try {
-                if (pFd != null) {
-                    pFd.close();
-                }
-            } catch (IOException ex) {
-                // Nothing can be done at this point
-                Log.e(TAG, "Failed to close pFd.");
-            }
-        }
-        // If we make it to here, then something has gone wrong and we couldn't open a socket.
-        // The only reasonable condition that would cause that is resource unavailable.
-        return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
-    }
-
-    /** close a socket that has been been allocated by and registered with the system server */
-    @Override
-    public synchronized void closeUdpEncapsulationSocket(int resourceId) throws RemoteException {
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        releaseResource(userRecord.mEncapSocketRecords, resourceId);
-    }
-
-    /**
-     * Create a tunnel interface for use in IPSec tunnel mode. The system server will cache the
-     * tunnel interface and a record of its owner so that it can and must be freed when no longer
-     * needed.
-     */
-    @Override
-    public synchronized IpSecTunnelInterfaceResponse createTunnelInterface(
-            String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
-            String callingPackage) {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-        Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface");
-        Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
-        checkInetAddress(localAddr);
-        checkInetAddress(remoteAddr);
-
-        // TODO: Check that underlying network exists, and IP addresses not assigned to a different
-        //       network (b/72316676).
-
-        int callerUid = Binder.getCallingUid();
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(callerUid);
-        if (!userRecord.mTunnelQuotaTracker.isAvailable()) {
-            return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
-        }
-
-        final int resourceId = mNextResourceId++;
-        final int ikey = reserveNetId();
-        final int okey = reserveNetId();
-        String intfName = String.format("%s%d", INetd.IPSEC_INTERFACE_PREFIX, resourceId);
-
-        try {
-            // Calls to netd:
-            //       Create VTI
-            //       Add inbound/outbound global policies
-            //              (use reqid = 0)
-            mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId);
-
-            BinderUtils.withCleanCallingIdentity(() -> {
-                NetdUtils.setInterfaceUp(mNetd, intfName);
-            });
-
-            for (int selAddrFamily : ADDRESS_FAMILIES) {
-                // Always send down correct local/remote addresses for template.
-                mNetd.ipSecAddSecurityPolicy(
-                        callerUid,
-                        selAddrFamily,
-                        IpSecManager.DIRECTION_OUT,
-                        localAddr,
-                        remoteAddr,
-                        0,
-                        okey,
-                        0xffffffff,
-                        resourceId);
-                mNetd.ipSecAddSecurityPolicy(
-                        callerUid,
-                        selAddrFamily,
-                        IpSecManager.DIRECTION_IN,
-                        remoteAddr,
-                        localAddr,
-                        0,
-                        ikey,
-                        0xffffffff,
-                        resourceId);
-
-                // Add a forwarding policy on the tunnel interface. In order to support forwarding
-                // the IpSecTunnelInterface must have a forwarding policy matching the incoming SA.
-                //
-                // Unless a IpSecTransform is also applied against this interface in DIRECTION_FWD,
-                // forwarding will be blocked by default (as would be the case if this policy was
-                // absent).
-                //
-                // This is necessary only on the tunnel interface, and not any the interface to
-                // which traffic will be forwarded to.
-                mNetd.ipSecAddSecurityPolicy(
-                        callerUid,
-                        selAddrFamily,
-                        IpSecManager.DIRECTION_FWD,
-                        remoteAddr,
-                        localAddr,
-                        0,
-                        ikey,
-                        0xffffffff,
-                        resourceId);
-            }
-
-            userRecord.mTunnelInterfaceRecords.put(
-                    resourceId,
-                    new RefcountedResource<TunnelInterfaceRecord>(
-                            new TunnelInterfaceRecord(
-                                    resourceId,
-                                    intfName,
-                                    underlyingNetwork,
-                                    localAddr,
-                                    remoteAddr,
-                                    ikey,
-                                    okey,
-                                    resourceId),
-                            binder));
-            return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName);
-        } catch (RemoteException e) {
-            // Release keys if we got an error.
-            releaseNetId(ikey);
-            releaseNetId(okey);
-            throw e.rethrowFromSystemServer();
-        } catch (Throwable t) {
-            // Release keys if we got an error.
-            releaseNetId(ikey);
-            releaseNetId(okey);
-            throw t;
-        }
-    }
-
-    /**
-     * Adds a new local address to the tunnel interface. This allows packets to be sent and received
-     * from multiple local IP addresses over the same tunnel.
-     */
-    @Override
-    public synchronized void addAddressToTunnelInterface(
-            int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
-        // Get tunnelInterface record; if no such interface is found, will throw
-        // IllegalArgumentException
-        TunnelInterfaceRecord tunnelInterfaceInfo =
-                userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
-        try {
-            // We can assume general validity of the IP address, since we get them as a
-            // LinkAddress, which does some validation.
-            mNetd.interfaceAddAddress(
-                    tunnelInterfaceInfo.mInterfaceName,
-                    localAddr.getAddress().getHostAddress(),
-                    localAddr.getPrefixLength());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Remove a new local address from the tunnel interface. After removal, the address will no
-     * longer be available to send from, or receive on.
-     */
-    @Override
-    public synchronized void removeAddressFromTunnelInterface(
-            int tunnelResourceId, LinkAddress localAddr, String callingPackage) {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        // Get tunnelInterface record; if no such interface is found, will throw
-        // IllegalArgumentException
-        TunnelInterfaceRecord tunnelInterfaceInfo =
-                userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
-        try {
-            // We can assume general validity of the IP address, since we get them as a
-            // LinkAddress, which does some validation.
-            mNetd.interfaceDelAddress(
-                            tunnelInterfaceInfo.mInterfaceName,
-                            localAddr.getAddress().getHostAddress(),
-                            localAddr.getPrefixLength());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** Set TunnelInterface to use a specific underlying network. */
-    @Override
-    public synchronized void setNetworkForTunnelInterface(
-            int tunnelResourceId, Network underlyingNetwork, String callingPackage) {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-        Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
-
-        final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
-        // Get tunnelInterface record; if no such interface is found, will throw
-        // IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null
-        final TunnelInterfaceRecord tunnelInterfaceInfo =
-                userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
-        final ConnectivityManager connectivityManager =
-                mContext.getSystemService(ConnectivityManager.class);
-        final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork);
-        if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) {
-            throw new IllegalArgumentException(
-                    "Underlying network cannot be the network being exposed by this tunnel");
-        }
-
-        // It is meaningless to check if the network exists or is valid because the network might
-        // disconnect at any time after it passes the check.
-
-        tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork);
-    }
-
-    /**
-     * Delete a TunnelInterface that has been been allocated by and registered with the system
-     * server
-     */
-    @Override
-    public synchronized void deleteTunnelInterface(
-            int resourceId, String callingPackage) throws RemoteException {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        releaseResource(userRecord.mTunnelInterfaceRecords, resourceId);
-    }
-
-    @VisibleForTesting
-    void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException {
-        IpSecAlgorithm auth = config.getAuthentication();
-        IpSecAlgorithm crypt = config.getEncryption();
-        IpSecAlgorithm aead = config.getAuthenticatedEncryption();
-
-        // Validate the algorithm set
-        Preconditions.checkArgument(
-                aead != null || crypt != null || auth != null,
-                "No Encryption or Authentication algorithms specified");
-        Preconditions.checkArgument(
-                auth == null || auth.isAuthentication(),
-                "Unsupported algorithm for Authentication");
-        Preconditions.checkArgument(
-                crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption");
-        Preconditions.checkArgument(
-                aead == null || aead.isAead(),
-                "Unsupported algorithm for Authenticated Encryption");
-        Preconditions.checkArgument(
-                aead == null || (auth == null && crypt == null),
-                "Authenticated Encryption is mutually exclusive with other Authentication "
-                        + "or Encryption algorithms");
-    }
-
-    private int getFamily(String inetAddress) {
-        int family = AF_UNSPEC;
-        InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress);
-        if (checkAddress instanceof Inet4Address) {
-            family = AF_INET;
-        } else if (checkAddress instanceof Inet6Address) {
-            family = AF_INET6;
-        }
-        return family;
-    }
-
-    /**
-     * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an
-     * IllegalArgumentException if they are not.
-     */
-    private void checkIpSecConfig(IpSecConfig config) {
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-
-        switch (config.getEncapType()) {
-            case IpSecTransform.ENCAP_NONE:
-                break;
-            case IpSecTransform.ENCAP_ESPINUDP:
-            case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
-                // Retrieve encap socket record; will throw IllegalArgumentException if not found
-                userRecord.mEncapSocketRecords.getResourceOrThrow(
-                        config.getEncapSocketResourceId());
-
-                int port = config.getEncapRemotePort();
-                if (port <= 0 || port > 0xFFFF) {
-                    throw new IllegalArgumentException("Invalid remote UDP port: " + port);
-                }
-                break;
-            default:
-                throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
-        }
-
-        validateAlgorithms(config);
-
-        // Retrieve SPI record; will throw IllegalArgumentException if not found
-        SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId());
-
-        // Check to ensure that SPI has not already been used.
-        if (s.getOwnedByTransform()) {
-            throw new IllegalStateException("SPI already in use; cannot be used in new Transforms");
-        }
-
-        // If no remote address is supplied, then use one from the SPI.
-        if (TextUtils.isEmpty(config.getDestinationAddress())) {
-            config.setDestinationAddress(s.getDestinationAddress());
-        }
-
-        // All remote addresses must match
-        if (!config.getDestinationAddress().equals(s.getDestinationAddress())) {
-            throw new IllegalArgumentException("Mismatched remote addresseses.");
-        }
-
-        // This check is technically redundant due to the chain of custody between the SPI and
-        // the IpSecConfig, but in the future if the dest is allowed to be set explicitly in
-        // the transform, this will prevent us from messing up.
-        checkInetAddress(config.getDestinationAddress());
-
-        // Require a valid source address for all transforms.
-        checkInetAddress(config.getSourceAddress());
-
-        // Check to ensure source and destination have the same address family.
-        String sourceAddress = config.getSourceAddress();
-        String destinationAddress = config.getDestinationAddress();
-        int sourceFamily = getFamily(sourceAddress);
-        int destinationFamily = getFamily(destinationAddress);
-        if (sourceFamily != destinationFamily) {
-            throw new IllegalArgumentException(
-                    "Source address ("
-                            + sourceAddress
-                            + ") and destination address ("
-                            + destinationAddress
-                            + ") have different address families.");
-        }
-
-        // Throw an error if UDP Encapsulation is not used in IPv4.
-        if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
-            throw new IllegalArgumentException(
-                    "UDP Encapsulation is not supported for this address family");
-        }
-
-        switch (config.getMode()) {
-            case IpSecTransform.MODE_TRANSPORT:
-                break;
-            case IpSecTransform.MODE_TUNNEL:
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "Invalid IpSecTransform.mode: " + config.getMode());
-        }
-
-        config.setMarkValue(0);
-        config.setMarkMask(0);
-    }
-
-    private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
-
-    private void enforceTunnelFeatureAndPermissions(String callingPackage) {
-        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
-            throw new UnsupportedOperationException(
-                    "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
-        }
-
-        Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels");
-
-        // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system
-        // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS
-        // permission or is the System Server.
-        if (AppOpsManager.MODE_ALLOWED == getAppOpsManager().noteOpNoThrow(
-                TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
-            return;
-        }
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
-    }
-
-    private void createOrUpdateTransform(
-            IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord)
-            throws RemoteException {
-
-        int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0;
-        if (encapType != IpSecTransform.ENCAP_NONE) {
-            encapLocalPort = socketRecord.getPort();
-            encapRemotePort = c.getEncapRemotePort();
-        }
-
-        IpSecAlgorithm auth = c.getAuthentication();
-        IpSecAlgorithm crypt = c.getEncryption();
-        IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption();
-
-        String cryptName;
-        if (crypt == null) {
-            cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : "";
-        } else {
-            cryptName = crypt.getName();
-        }
-
-        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());
-    }
-
-    /**
-     * Create a IPsec transform, which represents a single security association in the kernel. The
-     * transform will be cached by the system server and must be freed when no longer needed. It is
-     * possible to free one, deleting the SA from underneath sockets that are using it, which will
-     * result in all of those sockets becoming unable to send or receive data.
-     */
-    @Override
-    public synchronized IpSecTransformResponse createTransform(
-            IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
-        Objects.requireNonNull(c);
-        if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
-            enforceTunnelFeatureAndPermissions(callingPackage);
-        }
-        checkIpSecConfig(c);
-        Objects.requireNonNull(binder, "Null Binder passed to createTransform");
-        final int resourceId = mNextResourceId++;
-
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        List<RefcountedResource> dependencies = new ArrayList<>();
-
-        if (!userRecord.mTransformQuotaTracker.isAvailable()) {
-            return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
-        }
-
-        EncapSocketRecord socketRecord = null;
-        if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
-            RefcountedResource<EncapSocketRecord> refcountedSocketRecord =
-                    userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(
-                            c.getEncapSocketResourceId());
-            dependencies.add(refcountedSocketRecord);
-            socketRecord = refcountedSocketRecord.getResource();
-        }
-
-        RefcountedResource<SpiRecord> refcountedSpiRecord =
-                userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId());
-        dependencies.add(refcountedSpiRecord);
-        SpiRecord spiRecord = refcountedSpiRecord.getResource();
-
-        createOrUpdateTransform(c, resourceId, spiRecord, socketRecord);
-
-        // SA was created successfully, time to construct a record and lock it away
-        userRecord.mTransformRecords.put(
-                resourceId,
-                new RefcountedResource<TransformRecord>(
-                        new TransformRecord(resourceId, c, spiRecord, socketRecord),
-                        binder,
-                        dependencies.toArray(new RefcountedResource[dependencies.size()])));
-        return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId);
-    }
-
-    /**
-     * Delete a transport mode transform that was previously allocated by + registered with the
-     * system server. If this is called on an inactive (or non-existent) transform, it will not
-     * return an error. It's safe to de-allocate transforms that may have already been deleted for
-     * other reasons.
-     */
-    @Override
-    public synchronized void deleteTransform(int resourceId) throws RemoteException {
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
-        releaseResource(userRecord.mTransformRecords, resourceId);
-    }
-
-    /**
-     * Apply an active transport mode transform to a socket, which will apply the IPsec security
-     * association as a correspondent policy to the provided socket
-     */
-    @Override
-    public synchronized void applyTransportModeTransform(
-            ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException {
-        int callingUid = Binder.getCallingUid();
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
-        checkDirection(direction);
-        // Get transform record; if no transform is found, will throw IllegalArgumentException
-        TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId);
-
-        // TODO: make this a function.
-        if (info.mPid != getCallingPid() || info.mUid != callingUid) {
-            throw new SecurityException("Only the owner of an IpSec Transform may apply it!");
-        }
-
-        // Get config and check that to-be-applied transform has the correct mode
-        IpSecConfig c = info.getConfig();
-        Preconditions.checkArgument(
-                c.getMode() == IpSecTransform.MODE_TRANSPORT,
-                "Transform mode was not Transport mode; cannot be applied to a socket");
-
-        mNetd.ipSecApplyTransportModeTransform(
-                socket,
-                callingUid,
-                direction,
-                c.getSourceAddress(),
-                c.getDestinationAddress(),
-                info.getSpiRecord().getSpi());
-    }
-
-    /**
-     * Remove transport mode transforms from a socket, applying the default (empty) policy. This
-     * ensures that NO IPsec policy is applied to the socket (would be the equivalent of applying a
-     * policy that performs no IPsec). Today the resourceId parameter is passed but not used:
-     * reserved for future improved input validation.
-     */
-    @Override
-    public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket)
-            throws RemoteException {
-        mNetd.ipSecRemoveTransportModeTransform(socket);
-    }
-
-    /**
-     * Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec
-     * security association as a correspondent policy to the provided interface
-     */
-    @Override
-    public synchronized void applyTunnelModeTransform(
-            int tunnelResourceId, int direction,
-            int transformResourceId, String callingPackage) throws RemoteException {
-        enforceTunnelFeatureAndPermissions(callingPackage);
-        checkDirection(direction);
-
-        int callingUid = Binder.getCallingUid();
-        UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
-
-        // Get transform record; if no transform is found, will throw IllegalArgumentException
-        TransformRecord transformInfo =
-                userRecord.mTransformRecords.getResourceOrThrow(transformResourceId);
-
-        // Get tunnelInterface record; if no such interface is found, will throw
-        // IllegalArgumentException
-        TunnelInterfaceRecord tunnelInterfaceInfo =
-                userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId);
-
-        // Get config and check that to-be-applied transform has the correct mode
-        IpSecConfig c = transformInfo.getConfig();
-        Preconditions.checkArgument(
-                c.getMode() == IpSecTransform.MODE_TUNNEL,
-                "Transform mode was not Tunnel mode; cannot be applied to a tunnel interface");
-
-        EncapSocketRecord socketRecord = null;
-        if (c.getEncapType() != IpSecTransform.ENCAP_NONE) {
-            socketRecord =
-                    userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId());
-        }
-        SpiRecord spiRecord = transformInfo.getSpiRecord();
-
-        int mark =
-                (direction == IpSecManager.DIRECTION_OUT)
-                        ? tunnelInterfaceInfo.getOkey()
-                        : tunnelInterfaceInfo.getIkey(); // Ikey also used for FWD policies
-
-        try {
-            // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip
-            // SPI matching as part of the template resolution.
-            int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
-            c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId());
-
-            // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream
-            //     (and backporting) would allow us to narrow the mark space, and ensure that the SA
-            //     and SPs have matching marks (as VTI are meant to be built).
-            // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the
-            //     config matches the actual allocated resources in the kernel.
-            // All SAs will have zero marks (from creation time), and any policy that matches the
-            //     same src/dst could match these SAs. Non-IpSecService governed processes that
-            //     establish floating policies with the same src/dst may result in undefined
-            //     behavior. This is generally limited to vendor code due to the permissions
-            //     (CAP_NET_ADMIN) required.
-            //
-            // c.setMarkValue(mark);
-            // c.setMarkMask(0xffffffff);
-
-            if (direction == IpSecManager.DIRECTION_OUT) {
-                // Set output mark via underlying network (output only)
-                c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork());
-
-                // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys,
-                // but want to guarantee outbound packets are sent over the new SA.
-                spi = spiRecord.getSpi();
-            }
-
-            // Always update the policy with the relevant XFRM_IF_ID
-            for (int selAddrFamily : ADDRESS_FAMILIES) {
-                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)
-            createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord);
-        } catch (ServiceSpecificException e) {
-            if (e.errorCode == EINVAL) {
-                throw new IllegalArgumentException(e.toString());
-            } else {
-                throw e;
-            }
-        }
-    }
-
-    @Override
-    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
-
-        pw.println("IpSecService dump:");
-        pw.println();
-
-        pw.println("mUserResourceTracker:");
-        pw.println(mUserResourceTracker);
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
deleted file mode 100644
index ec8d779..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
-import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.util.LocalLog;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.Objects;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Generic connector class for interfacing with a native daemon which uses the
- * {@code libsysutils} FrameworkListener protocol.
- */
-final class NativeDaemonConnector implements Runnable, Handler.Callback {
-    private final static boolean VDBG = false;
-
-    private final String TAG;
-
-    private String mSocket;
-    private OutputStream mOutputStream;
-    private LocalLog mLocalLog;
-
-    private volatile boolean mDebug = false;
-    private volatile Object mWarnIfHeld;
-
-    private final ResponseQueue mResponseQueue;
-
-    private final PowerManager.WakeLock mWakeLock;
-
-    private final Looper mLooper;
-
-    private INativeDaemonConnectorCallbacks mCallbacks;
-    private Handler mCallbackHandler;
-
-    private AtomicInteger mSequenceNumber;
-
-    private static final long DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */
-    private static final long WARN_EXECUTE_DELAY_MS = 500; /* .5 sec */
-
-    /** Lock held whenever communicating with native daemon. */
-    private final Object mDaemonLock = new Object();
-
-    private final int BUFFER_SIZE = 4096;
-
-    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
-            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
-        mCallbacks = callbacks;
-        mSocket = socket;
-        mResponseQueue = new ResponseQueue(responseQueueSize);
-        mWakeLock = wl;
-        if (mWakeLock != null) {
-            mWakeLock.setReferenceCounted(true);
-        }
-        mSequenceNumber = new AtomicInteger(0);
-        TAG = logTag != null ? logTag : "NativeDaemonConnector";
-        mLocalLog = new LocalLog(maxLogSize);
-        final HandlerThread thread = new HandlerThread(TAG);
-        thread.start();
-        mLooper = thread.getLooper();
-    }
-
-    /**
-     * Enable Set debugging mode, which causes messages to also be written to both
-     * {@link Log} in addition to internal log.
-     */
-    public void setDebug(boolean debug) {
-        mDebug = debug;
-    }
-
-    /**
-     * Like SystemClock.uptimeMillis, except truncated to an int so it will fit in a message arg.
-     * Inaccurate across 49.7 days of uptime, but only used for debugging.
-     */
-    private int uptimeMillisInt() {
-        return (int) SystemClock.uptimeMillis() & Integer.MAX_VALUE;
-    }
-
-    /**
-     * Yell loudly if someone tries making future {@link #execute(Command)}
-     * calls while holding a lock on the given object.
-     */
-    public void setWarnIfHeld(Object warnIfHeld) {
-        if (mWarnIfHeld != null) {
-            throw new IllegalStateException("warnIfHeld is already set.");
-        }
-        mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
-    }
-
-    @Override
-    public void run() {
-        mCallbackHandler = new Handler(mLooper, this);
-
-        while (true) {
-            try {
-                listenToSocket();
-            } catch (Exception e) {
-                loge("Error in NativeDaemonConnector: " + e);
-                SystemClock.sleep(5000);
-            }
-        }
-    }
-
-    @Override
-    public boolean handleMessage(Message msg) {
-        final String event = (String) msg.obj;
-        final int start = uptimeMillisInt();
-        final int sent = msg.arg1;
-        try {
-            if (!mCallbacks.onEvent(msg.what, event, NativeDaemonEvent.unescapeArgs(event))) {
-                log(String.format("Unhandled event '%s'", event));
-            }
-        } catch (Exception e) {
-            loge("Error handling '" + event + "': " + e);
-        } finally {
-            if (mCallbacks.onCheckHoldWakeLock(msg.what) && mWakeLock != null) {
-                mWakeLock.release();
-            }
-            final int end = uptimeMillisInt();
-            if (start > sent && start - sent > WARN_EXECUTE_DELAY_MS) {
-                loge(String.format("NDC event {%s} processed too late: %dms", event, start - sent));
-            }
-            if (end > start && end - start > WARN_EXECUTE_DELAY_MS) {
-                loge(String.format("NDC event {%s} took too long: %dms", event, end - start));
-            }
-        }
-        return true;
-    }
-
-    private LocalSocketAddress determineSocketAddress() {
-        // If we're testing, set up a socket in a namespace that's accessible to test code.
-        // In order to ensure that unprivileged apps aren't able to impersonate native daemons on
-        // production devices, even if said native daemons ill-advisedly pick a socket name that
-        // starts with __test__, only allow this on debug builds.
-        if (mSocket.startsWith("__test__") && Build.isDebuggable()) {
-            return new LocalSocketAddress(mSocket);
-        } else {
-            return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED);
-        }
-    }
-
-    private void listenToSocket() throws IOException {
-        LocalSocket socket = null;
-
-        try {
-            socket = new LocalSocket();
-            LocalSocketAddress address = determineSocketAddress();
-
-            socket.connect(address);
-
-            InputStream inputStream = socket.getInputStream();
-            synchronized (mDaemonLock) {
-                mOutputStream = socket.getOutputStream();
-            }
-
-            mCallbacks.onDaemonConnected();
-
-            FileDescriptor[] fdList = null;
-            byte[] buffer = new byte[BUFFER_SIZE];
-            int start = 0;
-
-            while (true) {
-                int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
-                if (count < 0) {
-                    loge("got " + count + " reading with start = " + start);
-                    break;
-                }
-                fdList = socket.getAncillaryFileDescriptors();
-
-                // Add our starting point to the count and reset the start.
-                count += start;
-                start = 0;
-
-                for (int i = 0; i < count; i++) {
-                    if (buffer[i] == 0) {
-                        // Note - do not log this raw message since it may contain
-                        // sensitive data
-                        final String rawEvent = new String(
-                                buffer, start, i - start, StandardCharsets.UTF_8);
-
-                        boolean releaseWl = false;
-                        try {
-                            final NativeDaemonEvent event =
-                                    NativeDaemonEvent.parseRawEvent(rawEvent, fdList);
-
-                            log("RCV <- {" + event + "}");
-
-                            if (event.isClassUnsolicited()) {
-                                // TODO: migrate to sending NativeDaemonEvent instances
-                                if (mCallbacks.onCheckHoldWakeLock(event.getCode())
-                                        && mWakeLock != null) {
-                                    mWakeLock.acquire();
-                                    releaseWl = true;
-                                }
-                                Message msg = mCallbackHandler.obtainMessage(
-                                        event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
-                                if (mCallbackHandler.sendMessage(msg)) {
-                                    releaseWl = false;
-                                }
-                            } else {
-                                mResponseQueue.add(event.getCmdNumber(), event);
-                            }
-                        } catch (IllegalArgumentException e) {
-                            log("Problem parsing message " + e);
-                        } finally {
-                            if (releaseWl) {
-                                mWakeLock.release();
-                            }
-                        }
-
-                        start = i + 1;
-                    }
-                }
-
-                if (start == 0) {
-                    log("RCV incomplete");
-                }
-
-                // We should end at the amount we read. If not, compact then
-                // buffer and read again.
-                if (start != count) {
-                    final int remaining = BUFFER_SIZE - start;
-                    System.arraycopy(buffer, start, buffer, 0, remaining);
-                    start = remaining;
-                } else {
-                    start = 0;
-                }
-            }
-        } catch (IOException ex) {
-            loge("Communications error: " + ex);
-            throw ex;
-        } finally {
-            synchronized (mDaemonLock) {
-                if (mOutputStream != null) {
-                    try {
-                        loge("closing stream for " + mSocket);
-                        mOutputStream.close();
-                    } catch (IOException e) {
-                        loge("Failed closing output stream: " + e);
-                    }
-                    mOutputStream = null;
-                }
-            }
-
-            try {
-                if (socket != null) {
-                    socket.close();
-                }
-            } catch (IOException ex) {
-                loge("Failed closing socket: " + ex);
-            }
-        }
-    }
-
-    /**
-     * Wrapper around argument that indicates it's sensitive and shouldn't be
-     * logged.
-     */
-    public static class SensitiveArg {
-        private final Object mArg;
-
-        public SensitiveArg(Object arg) {
-            mArg = arg;
-        }
-
-        @Override
-        public String toString() {
-            return String.valueOf(mArg);
-        }
-    }
-
-    /**
-     * Make command for daemon, escaping arguments as needed.
-     */
-    @VisibleForTesting
-    static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
-            String cmd, Object... args) {
-        if (cmd.indexOf('\0') >= 0) {
-            throw new IllegalArgumentException("Unexpected command: " + cmd);
-        }
-        if (cmd.indexOf(' ') >= 0) {
-            throw new IllegalArgumentException("Arguments must be separate from command");
-        }
-
-        rawBuilder.append(sequenceNumber).append(' ').append(cmd);
-        logBuilder.append(sequenceNumber).append(' ').append(cmd);
-        for (Object arg : args) {
-            final String argString = String.valueOf(arg);
-            if (argString.indexOf('\0') >= 0) {
-                throw new IllegalArgumentException("Unexpected argument: " + arg);
-            }
-
-            rawBuilder.append(' ');
-            logBuilder.append(' ');
-
-            appendEscaped(rawBuilder, argString);
-            if (arg instanceof SensitiveArg) {
-                logBuilder.append("[scrubbed]");
-            } else {
-                appendEscaped(logBuilder, argString);
-            }
-        }
-
-        rawBuilder.append('\0');
-    }
-
-    /**
-     * Method that waits until all asychronous notifications sent by the native daemon have
-     * been processed. This method must not be called on the notification thread or an
-     * exception will be thrown.
-     */
-    public void waitForCallbacks() {
-        if (Thread.currentThread() == mLooper.getThread()) {
-            throw new IllegalStateException("Must not call this method on callback thread");
-        }
-
-        final CountDownLatch latch = new CountDownLatch(1);
-        mCallbackHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                latch.countDown();
-            }
-        });
-        try {
-            latch.await();
-        } catch (InterruptedException e) {
-            Log.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
-        }
-    }
-
-    /**
-     * Issue the given command to the native daemon and return a single expected
-     * response.
-     *
-     * @throws NativeDaemonConnectorException when problem communicating with
-     *             native daemon, or if the response matches
-     *             {@link NativeDaemonEvent#isClassClientError()} or
-     *             {@link NativeDaemonEvent#isClassServerError()}.
-     */
-    public NativeDaemonEvent execute(Command cmd) throws NativeDaemonConnectorException {
-        return execute(cmd.mCmd, cmd.mArguments.toArray());
-    }
-
-    /**
-     * Issue the given command to the native daemon and return a single expected
-     * response. Any arguments must be separated from base command so they can
-     * be properly escaped.
-     *
-     * @throws NativeDaemonConnectorException when problem communicating with
-     *             native daemon, or if the response matches
-     *             {@link NativeDaemonEvent#isClassClientError()} or
-     *             {@link NativeDaemonEvent#isClassServerError()}.
-     */
-    public NativeDaemonEvent execute(String cmd, Object... args)
-            throws NativeDaemonConnectorException {
-        return execute(DEFAULT_TIMEOUT, cmd, args);
-    }
-
-    public NativeDaemonEvent execute(long timeoutMs, String cmd, Object... args)
-            throws NativeDaemonConnectorException {
-        final NativeDaemonEvent[] events = executeForList(timeoutMs, cmd, args);
-        if (events.length != 1) {
-            throw new NativeDaemonConnectorException(
-                    "Expected exactly one response, but received " + events.length);
-        }
-        return events[0];
-    }
-
-    /**
-     * Issue the given command to the native daemon and return any
-     * {@link NativeDaemonEvent#isClassContinue()} responses, including the
-     * final terminal response.
-     *
-     * @throws NativeDaemonConnectorException when problem communicating with
-     *             native daemon, or if the response matches
-     *             {@link NativeDaemonEvent#isClassClientError()} or
-     *             {@link NativeDaemonEvent#isClassServerError()}.
-     */
-    public NativeDaemonEvent[] executeForList(Command cmd) throws NativeDaemonConnectorException {
-        return executeForList(cmd.mCmd, cmd.mArguments.toArray());
-    }
-
-    /**
-     * Issue the given command to the native daemon and return any
-     * {@link NativeDaemonEvent#isClassContinue()} responses, including the
-     * final terminal response. Any arguments must be separated from base
-     * command so they can be properly escaped.
-     *
-     * @throws NativeDaemonConnectorException when problem communicating with
-     *             native daemon, or if the response matches
-     *             {@link NativeDaemonEvent#isClassClientError()} or
-     *             {@link NativeDaemonEvent#isClassServerError()}.
-     */
-    public NativeDaemonEvent[] executeForList(String cmd, Object... args)
-            throws NativeDaemonConnectorException {
-        return executeForList(DEFAULT_TIMEOUT, cmd, args);
-    }
-
-    /**
-     * Issue the given command to the native daemon and return any {@linke
-     * NativeDaemonEvent@isClassContinue()} responses, including the final
-     * terminal response. Note that the timeout does not count time in deep
-     * sleep. Any arguments must be separated from base command so they can be
-     * properly escaped.
-     *
-     * @throws NativeDaemonConnectorException when problem communicating with
-     *             native daemon, or if the response matches
-     *             {@link NativeDaemonEvent#isClassClientError()} or
-     *             {@link NativeDaemonEvent#isClassServerError()}.
-     */
-    public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
-            throws NativeDaemonConnectorException {
-        if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
-            Log.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
-                    + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
-        }
-
-        final long startTime = SystemClock.elapsedRealtime();
-
-        final ArrayList<NativeDaemonEvent> events = new ArrayList<>();
-
-        final StringBuilder rawBuilder = new StringBuilder();
-        final StringBuilder logBuilder = new StringBuilder();
-        final int sequenceNumber = mSequenceNumber.incrementAndGet();
-
-        makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
-
-        final String rawCmd = rawBuilder.toString();
-        final String logCmd = logBuilder.toString();
-
-        log("SND -> {" + logCmd + "}");
-
-        synchronized (mDaemonLock) {
-            if (mOutputStream == null) {
-                throw new NativeDaemonConnectorException("missing output stream");
-            } else {
-                try {
-                    mOutputStream.write(rawCmd.getBytes(StandardCharsets.UTF_8));
-                } catch (IOException e) {
-                    throw new NativeDaemonConnectorException("problem sending command", e);
-                }
-            }
-        }
-
-        NativeDaemonEvent event = null;
-        do {
-            event = mResponseQueue.remove(sequenceNumber, timeoutMs, logCmd);
-            if (event == null) {
-                loge("timed-out waiting for response to " + logCmd);
-                throw new NativeDaemonTimeoutException(logCmd, event);
-            }
-            if (VDBG) log("RMV <- {" + event + "}");
-            events.add(event);
-        } while (event.isClassContinue());
-
-        final long endTime = SystemClock.elapsedRealtime();
-        if (endTime - startTime > WARN_EXECUTE_DELAY_MS) {
-            loge("NDC Command {" + logCmd + "} took too long (" + (endTime - startTime) + "ms)");
-        }
-
-        if (event.isClassClientError()) {
-            throw new NativeDaemonArgumentException(logCmd, event);
-        }
-        if (event.isClassServerError()) {
-            throw new NativeDaemonFailureException(logCmd, event);
-        }
-
-        return events.toArray(new NativeDaemonEvent[events.size()]);
-    }
-
-    /**
-     * Append the given argument to {@link StringBuilder}, escaping as needed,
-     * and surrounding with quotes when it contains spaces.
-     */
-    @VisibleForTesting
-    static void appendEscaped(StringBuilder builder, String arg) {
-        final boolean hasSpaces = arg.indexOf(' ') >= 0;
-        if (hasSpaces) {
-            builder.append('"');
-        }
-
-        final int length = arg.length();
-        for (int i = 0; i < length; i++) {
-            final char c = arg.charAt(i);
-
-            if (c == '"') {
-                builder.append("\\\"");
-            } else if (c == '\\') {
-                builder.append("\\\\");
-            } else {
-                builder.append(c);
-            }
-        }
-
-        if (hasSpaces) {
-            builder.append('"');
-        }
-    }
-
-    private static class NativeDaemonArgumentException extends NativeDaemonConnectorException {
-        public NativeDaemonArgumentException(String command, NativeDaemonEvent event) {
-            super(command, event);
-        }
-
-        @Override
-        public IllegalArgumentException rethrowAsParcelableException() {
-            throw new IllegalArgumentException(getMessage(), this);
-        }
-    }
-
-    private static class NativeDaemonFailureException extends NativeDaemonConnectorException {
-        public NativeDaemonFailureException(String command, NativeDaemonEvent event) {
-            super(command, event);
-        }
-    }
-
-    /**
-     * Command builder that handles argument list building. Any arguments must
-     * be separated from base command so they can be properly escaped.
-     */
-    public static class Command {
-        private String mCmd;
-        private ArrayList<Object> mArguments = new ArrayList<>();
-
-        public Command(String cmd, Object... args) {
-            mCmd = cmd;
-            for (Object arg : args) {
-                appendArg(arg);
-            }
-        }
-
-        public Command appendArg(Object arg) {
-            mArguments.add(arg);
-            return this;
-        }
-    }
-
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        mLocalLog.dump(fd, pw, args);
-        pw.println();
-        mResponseQueue.dump(fd, pw, args);
-    }
-
-    private void log(String logstring) {
-        if (mDebug) Log.d(TAG, logstring);
-        mLocalLog.log(logstring);
-    }
-
-    private void loge(String logstring) {
-        Log.e(TAG, logstring);
-        mLocalLog.log(logstring);
-    }
-
-    private static class ResponseQueue {
-
-        private static class PendingCmd {
-            public final int cmdNum;
-            public final String logCmd;
-
-            public BlockingQueue<NativeDaemonEvent> responses =
-                    new ArrayBlockingQueue<NativeDaemonEvent>(10);
-
-            // The availableResponseCount member is used to track when we can remove this
-            // instance from the ResponseQueue.
-            // This is used under the protection of a sync of the mPendingCmds object.
-            // A positive value means we've had more writers retreive this object while
-            // a negative value means we've had more readers.  When we've had an equal number
-            // (it goes to zero) we can remove this object from the mPendingCmds list.
-            // Note that we may have more responses for this command (and more readers
-            // coming), but that would result in a new PendingCmd instance being created
-            // and added with the same cmdNum.
-            // Also note that when this goes to zero it just means a parity of readers and
-            // writers have retrieved this object - not that they are done using it.  The
-            // responses queue may well have more responses yet to be read or may get more
-            // responses added to it.  But all those readers/writers have retreived and
-            // hold references to this instance already so it can be removed from
-            // mPendingCmds queue.
-            public int availableResponseCount;
-
-            public PendingCmd(int cmdNum, String logCmd) {
-                this.cmdNum = cmdNum;
-                this.logCmd = logCmd;
-            }
-        }
-
-        private final LinkedList<PendingCmd> mPendingCmds;
-        private int mMaxCount;
-
-        ResponseQueue(int maxCount) {
-            mPendingCmds = new LinkedList<PendingCmd>();
-            mMaxCount = maxCount;
-        }
-
-        public void add(int cmdNum, NativeDaemonEvent response) {
-            PendingCmd found = null;
-            synchronized (mPendingCmds) {
-                for (PendingCmd pendingCmd : mPendingCmds) {
-                    if (pendingCmd.cmdNum == cmdNum) {
-                        found = pendingCmd;
-                        break;
-                    }
-                }
-                if (found == null) {
-                    // didn't find it - make sure our queue isn't too big before adding
-                    while (mPendingCmds.size() >= mMaxCount) {
-                        Log.e("NativeDaemonConnector.ResponseQueue",
-                                "more buffered than allowed: " + mPendingCmds.size() +
-                                " >= " + mMaxCount);
-                        // let any waiter timeout waiting for this
-                        PendingCmd pendingCmd = mPendingCmds.remove();
-                        Log.e("NativeDaemonConnector.ResponseQueue",
-                                "Removing request: " + pendingCmd.logCmd + " (" +
-                                pendingCmd.cmdNum + ")");
-                    }
-                    found = new PendingCmd(cmdNum, null);
-                    mPendingCmds.add(found);
-                }
-                found.availableResponseCount++;
-                // if a matching remove call has already retrieved this we can remove this
-                // instance from our list
-                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
-            }
-            try {
-                found.responses.put(response);
-            } catch (InterruptedException e) { }
-        }
-
-        // note that the timeout does not count time in deep sleep.  If you don't want
-        // the device to sleep, hold a wakelock
-        public NativeDaemonEvent remove(int cmdNum, long timeoutMs, String logCmd) {
-            PendingCmd found = null;
-            synchronized (mPendingCmds) {
-                for (PendingCmd pendingCmd : mPendingCmds) {
-                    if (pendingCmd.cmdNum == cmdNum) {
-                        found = pendingCmd;
-                        break;
-                    }
-                }
-                if (found == null) {
-                    found = new PendingCmd(cmdNum, logCmd);
-                    mPendingCmds.add(found);
-                }
-                found.availableResponseCount--;
-                // if a matching add call has already retrieved this we can remove this
-                // instance from our list
-                if (found.availableResponseCount == 0) mPendingCmds.remove(found);
-            }
-            NativeDaemonEvent result = null;
-            try {
-                result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {}
-            if (result == null) {
-                Log.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
-            }
-            return result;
-        }
-
-        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-            pw.println("Pending requests:");
-            synchronized (mPendingCmds) {
-                for (PendingCmd pendingCmd : mPendingCmds) {
-                    pw.println("  Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
-                }
-            }
-        }
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
deleted file mode 100644
index 4d8881c..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.os.Parcel;
-
-/**
- * An exception that indicates there was an error with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonConnectorException extends Exception {
-    private String mCmd;
-    private NativeDaemonEvent mEvent;
-
-    public NativeDaemonConnectorException(String detailMessage) {
-        super(detailMessage);
-    }
-
-    public NativeDaemonConnectorException(String detailMessage, Throwable throwable) {
-        super(detailMessage, throwable);
-    }
-
-    public NativeDaemonConnectorException(String cmd, NativeDaemonEvent event) {
-        super("command '" + cmd + "' failed with '" + event + "'");
-        mCmd = cmd;
-        mEvent = event;
-    }
-
-    public int getCode() {
-        return mEvent != null ? mEvent.getCode() : -1;
-    }
-
-    public String getCmd() {
-        return mCmd;
-    }
-
-    /**
-     * Rethrow as a {@link RuntimeException} subclass that is handled by
-     * {@link Parcel#writeException(Exception)}.
-     */
-    public IllegalArgumentException rethrowAsParcelableException() {
-        throw new IllegalStateException(getMessage(), this);
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
deleted file mode 100644
index 5683694..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.util.ArrayList;
-
-/**
- * Parsed event from native side of {@link NativeDaemonConnector}.
- */
-public class NativeDaemonEvent {
-
-    // TODO: keep class ranges in sync with ResponseCode.h
-    // TODO: swap client and server error ranges to roughly mirror HTTP spec
-
-    private final int mCmdNumber;
-    private final int mCode;
-    private final String mMessage;
-    private final String mRawEvent;
-    private final String mLogMessage;
-    private String[] mParsed;
-    private FileDescriptor[] mFdList;
-
-    private NativeDaemonEvent(int cmdNumber, int code, String message,
-                              String rawEvent, String logMessage, FileDescriptor[] fdList) {
-        mCmdNumber = cmdNumber;
-        mCode = code;
-        mMessage = message;
-        mRawEvent = rawEvent;
-        mLogMessage = logMessage;
-        mParsed = null;
-        mFdList = fdList;
-    }
-
-    static public final String SENSITIVE_MARKER = "{{sensitive}}";
-
-    public int getCmdNumber() {
-        return mCmdNumber;
-    }
-
-    public int getCode() {
-        return mCode;
-    }
-
-    public String getMessage() {
-        return mMessage;
-    }
-
-    public FileDescriptor[] getFileDescriptors() {
-        return mFdList;
-    }
-
-    @Deprecated
-    public String getRawEvent() {
-        return mRawEvent;
-    }
-
-    @Override
-    public String toString() {
-        return mLogMessage;
-    }
-
-    /**
-     * Test if event represents a partial response which is continued in
-     * additional subsequent events.
-     */
-    public boolean isClassContinue() {
-        return mCode >= 100 && mCode < 200;
-    }
-
-    /**
-     * Test if event represents a command success.
-     */
-    public boolean isClassOk() {
-        return mCode >= 200 && mCode < 300;
-    }
-
-    /**
-     * Test if event represents a remote native daemon error.
-     */
-    public boolean isClassServerError() {
-        return mCode >= 400 && mCode < 500;
-    }
-
-    /**
-     * Test if event represents a command syntax or argument error.
-     */
-    public boolean isClassClientError() {
-        return mCode >= 500 && mCode < 600;
-    }
-
-    /**
-     * Test if event represents an unsolicited event from native daemon.
-     */
-    public boolean isClassUnsolicited() {
-        return isClassUnsolicited(mCode);
-    }
-
-    private static boolean isClassUnsolicited(int code) {
-        return code >= 600 && code < 700;
-    }
-
-    /**
-     * Verify this event matches the given code.
-     *
-     * @throws IllegalStateException if {@link #getCode()} doesn't match.
-     */
-    public void checkCode(int code) {
-        if (mCode != code) {
-            throw new IllegalStateException("Expected " + code + " but was: " + this);
-        }
-    }
-
-    /**
-     * Parse the given raw event into {@link NativeDaemonEvent} instance.
-     *
-     * @throws IllegalArgumentException when line doesn't match format expected
-     *             from native side.
-     */
-    public static NativeDaemonEvent parseRawEvent(String rawEvent, FileDescriptor[] fdList) {
-        final String[] parsed = rawEvent.split(" ");
-        if (parsed.length < 2) {
-            throw new IllegalArgumentException("Insufficient arguments");
-        }
-
-        int skiplength = 0;
-
-        final int code;
-        try {
-            code = Integer.parseInt(parsed[0]);
-            skiplength = parsed[0].length() + 1;
-        } catch (NumberFormatException e) {
-            throw new IllegalArgumentException("problem parsing code", e);
-        }
-
-        int cmdNumber = -1;
-        if (isClassUnsolicited(code) == false) {
-            if (parsed.length < 3) {
-                throw new IllegalArgumentException("Insufficient arguemnts");
-            }
-            try {
-                cmdNumber = Integer.parseInt(parsed[1]);
-                skiplength += parsed[1].length() + 1;
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException("problem parsing cmdNumber", e);
-            }
-        }
-
-        String logMessage = rawEvent;
-        if (parsed.length > 2 && parsed[2].equals(SENSITIVE_MARKER)) {
-            skiplength += parsed[2].length() + 1;
-            logMessage = parsed[0] + " " + parsed[1] + " {}";
-        }
-
-        final String message = rawEvent.substring(skiplength);
-
-        return new NativeDaemonEvent(cmdNumber, code, message, rawEvent, logMessage, fdList);
-    }
-
-    /**
-     * Filter the given {@link NativeDaemonEvent} list, returning
-     * {@link #getMessage()} for any events matching the requested code.
-     */
-    public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
-        final ArrayList<String> result = new ArrayList<>();
-        for (NativeDaemonEvent event : events) {
-            if (event.getCode() == matchCode) {
-                result.add(event.getMessage());
-            }
-        }
-        return result.toArray(new String[result.size()]);
-    }
-
-    /**
-     * Find the Nth field of the event.
-     *
-     * This ignores and code or cmdNum, the first return value is given for N=0.
-     * Also understands "\"quoted\" multiword responses" and tries them as a single field
-     */
-    public String getField(int n) {
-        if (mParsed == null) {
-            mParsed = unescapeArgs(mRawEvent);
-        }
-        n += 2; // skip code and command#
-        if (n > mParsed.length) return null;
-            return mParsed[n];
-        }
-
-    public static String[] unescapeArgs(String rawEvent) {
-        final boolean DEBUG_ROUTINE = false;
-        final String LOGTAG = "unescapeArgs";
-        final ArrayList<String> parsed = new ArrayList<String>();
-        final int length = rawEvent.length();
-        int current = 0;
-        int wordEnd = -1;
-        boolean quoted = false;
-
-        if (DEBUG_ROUTINE) Log.e(LOGTAG, "parsing '" + rawEvent + "'");
-        if (rawEvent.charAt(current) == '\"') {
-            quoted = true;
-            current++;
-        }
-        while (current < length) {
-            // find the end of the word
-            char terminator = quoted ? '\"' : ' ';
-            wordEnd = current;
-            while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
-                if (rawEvent.charAt(wordEnd) == '\\') {
-                    // skip the escaped char
-                    ++wordEnd;
-                }
-                ++wordEnd;
-            }
-            if (wordEnd > length) wordEnd = length;
-            String word = rawEvent.substring(current, wordEnd);
-            current += word.length();
-            if (!quoted) {
-                word = word.trim();
-            } else {
-                current++;  // skip the trailing quote
-            }
-            // unescape stuff within the word
-            word = word.replace("\\\\", "\\");
-            word = word.replace("\\\"", "\"");
-
-            if (DEBUG_ROUTINE) Log.e(LOGTAG, "found '" + word + "'");
-            parsed.add(word);
-
-            // find the beginning of the next word - either of these options
-            int nextSpace = rawEvent.indexOf(' ', current);
-            int nextQuote = rawEvent.indexOf(" \"", current);
-            if (DEBUG_ROUTINE) {
-                Log.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
-            }
-            if (nextQuote > -1 && nextQuote <= nextSpace) {
-                quoted = true;
-                current = nextQuote + 2;
-            } else {
-                quoted = false;
-                if (nextSpace > -1) {
-                    current = nextSpace + 1;
-                }
-            } // else we just start the next word after the current and read til the end
-            if (DEBUG_ROUTINE) {
-                Log.e(LOGTAG, "next loop - current=" + current
-                        + ", length=" + length + ", quoted=" + quoted);
-            }
-        }
-        return parsed.toArray(new String[parsed.size()]);
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
deleted file mode 100644
index 658f7d6..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-/**
- * An exception that indicates there was a timeout with a
- * {@link NativeDaemonConnector} operation.
- */
-public class NativeDaemonTimeoutException extends NativeDaemonConnectorException {
-    public NativeDaemonTimeoutException(String command, NativeDaemonEvent event) {
-        super(command, event);
-    }
-}
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
deleted file mode 100644
index ddf6d2c..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/NsdService.java
+++ /dev/null
@@ -1,1146 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.nsd.INsdManager;
-import android.net.nsd.INsdManagerCallback;
-import android.net.nsd.INsdServiceConnector;
-import android.net.nsd.NsdManager;
-import android.net.nsd.NsdServiceInfo;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Base64;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-import com.android.net.module.util.DnsSdTxtRecord;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Network Service Discovery Service handles remote service discovery operation requests by
- * implementing the INsdManager interface.
- *
- * @hide
- */
-public class NsdService extends INsdManager.Stub {
-    private static final String TAG = "NsdService";
-    private static final String MDNS_TAG = "mDnsConnector";
-
-    private static final boolean DBG = true;
-    private static final long CLEANUP_DELAY_MS = 10000;
-    private static final int IFACE_IDX_ANY = 0;
-
-    private final Context mContext;
-    private final NsdStateMachine mNsdStateMachine;
-    private final DaemonConnection mDaemon;
-    private final NativeCallbackReceiver mDaemonCallback;
-
-    /**
-     * Clients receiving asynchronous messages
-     */
-    private final HashMap<NsdServiceConnector, ClientInfo> mClients = new HashMap<>();
-
-    /* A map from unique id to client info */
-    private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
-
-    private final long mCleanupDelayMs;
-
-    private static final int INVALID_ID = 0;
-    private int mUniqueId = 1;
-    // The count of the connected legacy clients.
-    private int mLegacyClientCount = 0;
-
-    private class NsdStateMachine extends StateMachine {
-
-        private final DefaultState mDefaultState = new DefaultState();
-        private final DisabledState mDisabledState = new DisabledState();
-        private final EnabledState mEnabledState = new EnabledState();
-
-        @Override
-        protected String getWhatToString(int what) {
-            return NsdManager.nameOf(what);
-        }
-
-        private void maybeStartDaemon() {
-            mDaemon.maybeStart();
-            maybeScheduleStop();
-        }
-
-        private boolean isAnyRequestActive() {
-            return mIdToClientInfoMap.size() != 0;
-        }
-
-        private void scheduleStop() {
-            sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs);
-        }
-        private void maybeScheduleStop() {
-            // The native daemon should stay alive and can't be cleanup
-            // if any legacy client connected.
-            if (!isAnyRequestActive() && mLegacyClientCount == 0) {
-                scheduleStop();
-            }
-        }
-
-        private void cancelStop() {
-            this.removeMessages(NsdManager.DAEMON_CLEANUP);
-        }
-
-        NsdStateMachine(String name, Handler handler) {
-            super(name, handler);
-            addState(mDefaultState);
-                addState(mDisabledState, mDefaultState);
-                addState(mEnabledState, mDefaultState);
-            State initialState = mEnabledState;
-            setInitialState(initialState);
-            setLogRecSize(25);
-        }
-
-        class DefaultState extends State {
-            @Override
-            public boolean processMessage(Message msg) {
-                final ClientInfo cInfo;
-                final int clientId = msg.arg2;
-                switch (msg.what) {
-                    case NsdManager.REGISTER_CLIENT:
-                        final Pair<NsdServiceConnector, INsdManagerCallback> arg =
-                                (Pair<NsdServiceConnector, INsdManagerCallback>) msg.obj;
-                        final INsdManagerCallback cb = arg.second;
-                        try {
-                            cb.asBinder().linkToDeath(arg.first, 0);
-                            cInfo = new ClientInfo(cb);
-                            mClients.put(arg.first, cInfo);
-                        } catch (RemoteException e) {
-                            Log.w(TAG, "Client " + clientId + " has already died");
-                        }
-                        break;
-                    case NsdManager.UNREGISTER_CLIENT:
-                        final NsdServiceConnector connector = (NsdServiceConnector) msg.obj;
-                        cInfo = mClients.remove(connector);
-                        if (cInfo != null) {
-                            cInfo.expungeAllRequests();
-                            if (cInfo.isLegacy()) {
-                                mLegacyClientCount -= 1;
-                            }
-                        }
-                        maybeScheduleStop();
-                        break;
-                    case NsdManager.DISCOVER_SERVICES:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cInfo.onDiscoverServicesFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                       break;
-                    case NsdManager.STOP_DISCOVERY:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cInfo.onStopDiscoveryFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.REGISTER_SERVICE:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cInfo.onRegisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.UNREGISTER_SERVICE:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cInfo.onUnregisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.RESOLVE_SERVICE:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.DAEMON_CLEANUP:
-                        mDaemon.maybeStop();
-                        break;
-                    // This event should be only sent by the legacy (target SDK < S) clients.
-                    // Mark the sending client as legacy.
-                    case NsdManager.DAEMON_STARTUP:
-                        cInfo = getClientInfoForReply(msg);
-                        if (cInfo != null) {
-                            cancelStop();
-                            cInfo.setLegacy();
-                            mLegacyClientCount += 1;
-                            maybeStartDaemon();
-                        }
-                        break;
-                    case NsdManager.NATIVE_DAEMON_EVENT:
-                    default:
-                        Log.e(TAG, "Unhandled " + msg);
-                        return NOT_HANDLED;
-                }
-                return HANDLED;
-            }
-
-            private ClientInfo getClientInfoForReply(Message msg) {
-                final ListenerArgs args = (ListenerArgs) msg.obj;
-                return mClients.get(args.connector);
-            }
-        }
-
-        class DisabledState extends State {
-            @Override
-            public void enter() {
-                sendNsdStateChangeBroadcast(false);
-            }
-
-            @Override
-            public boolean processMessage(Message msg) {
-                switch (msg.what) {
-                    case NsdManager.ENABLE:
-                        transitionTo(mEnabledState);
-                        break;
-                    default:
-                        return NOT_HANDLED;
-                }
-                return HANDLED;
-            }
-        }
-
-        class EnabledState extends State {
-            @Override
-            public void enter() {
-                sendNsdStateChangeBroadcast(true);
-            }
-
-            @Override
-            public void exit() {
-                // TODO: it is incorrect to stop the daemon without expunging all requests
-                // and sending error callbacks to clients.
-                scheduleStop();
-            }
-
-            private boolean requestLimitReached(ClientInfo clientInfo) {
-                if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
-                    if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
-                    return true;
-                }
-                return false;
-            }
-
-            private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
-                clientInfo.mClientIds.put(clientId, globalId);
-                clientInfo.mClientRequests.put(clientId, what);
-                mIdToClientInfoMap.put(globalId, clientInfo);
-                // Remove the cleanup event because here comes a new request.
-                cancelStop();
-            }
-
-            private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
-                clientInfo.mClientIds.delete(clientId);
-                clientInfo.mClientRequests.delete(clientId);
-                mIdToClientInfoMap.remove(globalId);
-                maybeScheduleStop();
-            }
-
-            @Override
-            public boolean processMessage(Message msg) {
-                final ClientInfo clientInfo;
-                final int id;
-                final int clientId = msg.arg2;
-                final ListenerArgs args;
-                switch (msg.what) {
-                    case NsdManager.DISABLE:
-                        //TODO: cleanup clients
-                        transitionTo(mDisabledState);
-                        break;
-                    case NsdManager.DISCOVER_SERVICES:
-                        if (DBG) Log.d(TAG, "Discover services");
-                        args = (ListenerArgs) msg.obj;
-                        clientInfo = mClients.get(args.connector);
-
-                        if (requestLimitReached(clientInfo)) {
-                            clientInfo.onDiscoverServicesFailed(
-                                    clientId, NsdManager.FAILURE_MAX_LIMIT);
-                            break;
-                        }
-
-                        maybeStartDaemon();
-                        id = getUniqueId();
-                        if (discoverServices(id, args.serviceInfo)) {
-                            if (DBG) {
-                                Log.d(TAG, "Discover " + msg.arg2 + " " + id
-                                        + args.serviceInfo.getServiceType());
-                            }
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
-                            clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
-                        } else {
-                            stopServiceDiscovery(id);
-                            clientInfo.onDiscoverServicesFailed(clientId,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.STOP_DISCOVERY:
-                        if (DBG) Log.d(TAG, "Stop service discovery");
-                        args = (ListenerArgs) msg.obj;
-                        clientInfo = mClients.get(args.connector);
-
-                        try {
-                            id = clientInfo.mClientIds.get(clientId);
-                        } catch (NullPointerException e) {
-                            clientInfo.onStopDiscoveryFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                            break;
-                        }
-                        removeRequestMap(clientId, id, clientInfo);
-                        if (stopServiceDiscovery(id)) {
-                            clientInfo.onStopDiscoverySucceeded(clientId);
-                        } else {
-                            clientInfo.onStopDiscoveryFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.REGISTER_SERVICE:
-                        if (DBG) Log.d(TAG, "Register service");
-                        args = (ListenerArgs) msg.obj;
-                        clientInfo = mClients.get(args.connector);
-                        if (requestLimitReached(clientInfo)) {
-                            clientInfo.onRegisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_MAX_LIMIT);
-                            break;
-                        }
-
-                        maybeStartDaemon();
-                        id = getUniqueId();
-                        if (registerService(id, args.serviceInfo)) {
-                            if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
-                            // Return success after mDns reports success
-                        } else {
-                            unregisterService(id);
-                            clientInfo.onRegisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.UNREGISTER_SERVICE:
-                        if (DBG) Log.d(TAG, "unregister service");
-                        args = (ListenerArgs) msg.obj;
-                        clientInfo = mClients.get(args.connector);
-                        if (clientInfo == null) {
-                            Log.e(TAG, "Unknown connector in unregistration");
-                            break;
-                        }
-                        id = clientInfo.mClientIds.get(clientId);
-                        removeRequestMap(clientId, id, clientInfo);
-                        if (unregisterService(id)) {
-                            clientInfo.onUnregisterServiceSucceeded(clientId);
-                        } else {
-                            clientInfo.onUnregisterServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.RESOLVE_SERVICE:
-                        if (DBG) Log.d(TAG, "Resolve service");
-                        args = (ListenerArgs) msg.obj;
-                        clientInfo = mClients.get(args.connector);
-
-                        if (clientInfo.mResolvedService != null) {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
-                            break;
-                        }
-
-                        maybeStartDaemon();
-                        id = getUniqueId();
-                        if (resolveService(id, args.serviceInfo)) {
-                            clientInfo.mResolvedService = new NsdServiceInfo();
-                            storeRequestMap(clientId, id, clientInfo, msg.what);
-                        } else {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        break;
-                    case NsdManager.NATIVE_DAEMON_EVENT:
-                        NativeEvent event = (NativeEvent) msg.obj;
-                        if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
-                            return NOT_HANDLED;
-                        }
-                        break;
-                    default:
-                        return NOT_HANDLED;
-                }
-                return HANDLED;
-            }
-
-            private boolean handleNativeEvent(int code, String raw, String[] cooked) {
-                NsdServiceInfo servInfo;
-                int id = Integer.parseInt(cooked[1]);
-                ClientInfo clientInfo = mIdToClientInfoMap.get(id);
-                if (clientInfo == null) {
-                    String name = NativeResponseCode.nameOf(code);
-                    Log.e(TAG, String.format("id %d for %s has no client mapping", id, name));
-                    return false;
-                }
-
-                /* This goes in response as msg.arg2 */
-                int clientId = clientInfo.getClientId(id);
-                if (clientId < 0) {
-                    // This can happen because of race conditions. For example,
-                    // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
-                    // and we may get in this situation.
-                    String name = NativeResponseCode.nameOf(code);
-                    Log.d(TAG, String.format(
-                            "Notification %s for listener id %d that is no longer active",
-                            name, id));
-                    return false;
-                }
-                if (DBG) {
-                    String name = NativeResponseCode.nameOf(code);
-                    Log.d(TAG, String.format("Native daemon message %s: %s", name, raw));
-                }
-                switch (code) {
-                    case NativeResponseCode.SERVICE_FOUND:
-                        /* NNN uniqueId serviceName regType domain interfaceIdx netId */
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
-                        final int foundNetId;
-                        try {
-                            foundNetId = Integer.parseInt(cooked[6]);
-                        } catch (NumberFormatException e) {
-                            Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
-                            break;
-                        }
-                        if (foundNetId == 0L) {
-                            // Ignore services that do not have a Network: they are not usable
-                            // by apps, as they would need privileged permissions to use
-                            // interfaces that do not have an associated Network.
-                            break;
-                        }
-                        servInfo.setNetwork(new Network(foundNetId));
-                        clientInfo.onServiceFound(clientId, servInfo);
-                        break;
-                    case NativeResponseCode.SERVICE_LOST:
-                        /* NNN uniqueId serviceName regType domain interfaceIdx netId */
-                        final int lostNetId;
-                        try {
-                            lostNetId = Integer.parseInt(cooked[6]);
-                        } catch (NumberFormatException e) {
-                            Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
-                            break;
-                        }
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
-                        // The network could be null if it was torn down when the service is lost
-                        // TODO: avoid returning null in that case, possibly by remembering found
-                        // services on the same interface index and their network at the time
-                        servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId));
-                        clientInfo.onServiceLost(clientId, servInfo);
-                        break;
-                    case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
-                        /* NNN uniqueId errorCode */
-                        clientInfo.onDiscoverServicesFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        break;
-                    case NativeResponseCode.SERVICE_REGISTERED:
-                        /* NNN regId serviceName regType */
-                        servInfo = new NsdServiceInfo(cooked[2], null);
-                        clientInfo.onRegisterServiceSucceeded(clientId, servInfo);
-                        break;
-                    case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
-                        /* NNN regId errorCode */
-                        clientInfo.onRegisterServiceFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        break;
-                    case NativeResponseCode.SERVICE_UPDATED:
-                        /* NNN regId */
-                        break;
-                    case NativeResponseCode.SERVICE_UPDATE_FAILED:
-                        /* NNN regId errorCode */
-                        break;
-                    case NativeResponseCode.SERVICE_RESOLVED:
-                        /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */
-                        int index = 0;
-                        while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
-                            if (cooked[2].charAt(index) == '\\') {
-                                ++index;
-                            }
-                            ++index;
-                        }
-                        if (index >= cooked[2].length()) {
-                            Log.e(TAG, "Invalid service found " + raw);
-                            break;
-                        }
-
-                        String name = cooked[2].substring(0, index);
-                        String rest = cooked[2].substring(index);
-                        String type = rest.replace(".local.", "");
-
-                        name = unescape(name);
-
-                        clientInfo.mResolvedService.setServiceName(name);
-                        clientInfo.mResolvedService.setServiceType(type);
-                        clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
-                        clientInfo.mResolvedService.setTxtRecords(cooked[6]);
-                        // Network will be added after SERVICE_GET_ADDR_SUCCESS
-
-                        stopResolveService(id);
-                        removeRequestMap(clientId, id, clientInfo);
-
-                        int id2 = getUniqueId();
-                        if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) {
-                            storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
-                        } else {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                            clientInfo.mResolvedService = null;
-                        }
-                        break;
-                    case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
-                        /* NNN resolveId errorCode */
-                        stopResolveService(id);
-                        removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
-                        clientInfo.onResolveServiceFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        break;
-                    case NativeResponseCode.SERVICE_GET_ADDR_FAILED:
-                        /* NNN resolveId errorCode */
-                        stopGetAddrInfo(id);
-                        removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
-                        clientInfo.onResolveServiceFailed(
-                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        break;
-                    case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
-                        /* NNN resolveId hostname ttl addr interfaceIdx netId */
-                        Network network = null;
-                        try {
-                            final int netId = Integer.parseInt(cooked[6]);
-                            network = netId == 0L ? null : new Network(netId);
-                        } catch (NumberFormatException e) {
-                            Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e);
-                        }
-
-                        InetAddress serviceHost = null;
-                        try {
-                            serviceHost = InetAddress.getByName(cooked[4]);
-                        } catch (UnknownHostException e) {
-                            Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e);
-                        }
-
-                        // If the resolved service is on an interface without a network, consider it
-                        // as a failure: it would not be usable by apps as they would need
-                        // privileged permissions.
-                        if (network != null && serviceHost != null) {
-                            clientInfo.mResolvedService.setHost(serviceHost);
-                            clientInfo.mResolvedService.setNetwork(network);
-                            clientInfo.onResolveServiceSucceeded(
-                                    clientId, clientInfo.mResolvedService);
-                        } else {
-                            clientInfo.onResolveServiceFailed(
-                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
-                        }
-                        stopGetAddrInfo(id);
-                        removeRequestMap(clientId, id, clientInfo);
-                        clientInfo.mResolvedService = null;
-                        break;
-                    default:
-                        return false;
-                }
-                return true;
-            }
-       }
-    }
-
-    private String unescape(String s) {
-        StringBuilder sb = new StringBuilder(s.length());
-        for (int i = 0; i < s.length(); ++i) {
-            char c = s.charAt(i);
-            if (c == '\\') {
-                if (++i >= s.length()) {
-                    Log.e(TAG, "Unexpected end of escape sequence in: " + s);
-                    break;
-                }
-                c = s.charAt(i);
-                if (c != '.' && c != '\\') {
-                    if (i + 2 >= s.length()) {
-                        Log.e(TAG, "Unexpected end of escape sequence in: " + s);
-                        break;
-                    }
-                    c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
-                    i += 2;
-                }
-            }
-            sb.append(c);
-        }
-        return sb.toString();
-    }
-
-    @VisibleForTesting
-    NsdService(Context ctx, Handler handler, DaemonConnectionSupplier fn, long cleanupDelayMs) {
-        mCleanupDelayMs = cleanupDelayMs;
-        mContext = ctx;
-        mNsdStateMachine = new NsdStateMachine(TAG, handler);
-        mNsdStateMachine.start();
-        mDaemonCallback = new NativeCallbackReceiver();
-        mDaemon = fn.get(mDaemonCallback);
-    }
-
-    public static NsdService create(Context context) throws InterruptedException {
-        HandlerThread thread = new HandlerThread(TAG);
-        thread.start();
-        Handler handler = new Handler(thread.getLooper());
-        NsdService service =
-                new NsdService(context, handler, DaemonConnection::new, CLEANUP_DELAY_MS);
-        service.mDaemonCallback.awaitConnection();
-        return service;
-    }
-
-    @Override
-    public INsdServiceConnector connect(INsdManagerCallback cb) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
-        final INsdServiceConnector connector = new NsdServiceConnector();
-        mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb)));
-        return connector;
-    }
-
-    private static class ListenerArgs {
-        public final NsdServiceConnector connector;
-        public final NsdServiceInfo serviceInfo;
-        ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) {
-            this.connector = connector;
-            this.serviceInfo = serviceInfo;
-        }
-    }
-
-    private class NsdServiceConnector extends INsdServiceConnector.Stub
-            implements IBinder.DeathRecipient  {
-        @Override
-        public void registerService(int listenerKey, NsdServiceInfo serviceInfo) {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.REGISTER_SERVICE, 0, listenerKey,
-                    new ListenerArgs(this, serviceInfo)));
-        }
-
-        @Override
-        public void unregisterService(int listenerKey) {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.UNREGISTER_SERVICE, 0, listenerKey,
-                    new ListenerArgs(this, null)));
-        }
-
-        @Override
-        public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.DISCOVER_SERVICES, 0, listenerKey,
-                    new ListenerArgs(this, serviceInfo)));
-        }
-
-        @Override
-        public void stopDiscovery(int listenerKey) {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.STOP_DISCOVERY, 0, listenerKey, new ListenerArgs(this, null)));
-        }
-
-        @Override
-        public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.RESOLVE_SERVICE, 0, listenerKey,
-                    new ListenerArgs(this, serviceInfo)));
-        }
-
-        @Override
-        public void startDaemon() {
-            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
-                    NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null)));
-        }
-
-        @Override
-        public void binderDied() {
-            mNsdStateMachine.sendMessage(
-                    mNsdStateMachine.obtainMessage(NsdManager.UNREGISTER_CLIENT, this));
-        }
-    }
-
-    private void sendNsdStateChangeBroadcast(boolean isEnabled) {
-        final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        int nsdState = isEnabled ? NsdManager.NSD_STATE_ENABLED : NsdManager.NSD_STATE_DISABLED;
-        intent.putExtra(NsdManager.EXTRA_NSD_STATE, nsdState);
-        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-    }
-
-    private int getUniqueId() {
-        if (++mUniqueId == INVALID_ID) return ++mUniqueId;
-        return mUniqueId;
-    }
-
-    /* These should be in sync with system/netd/server/ResponseCode.h */
-    static final class NativeResponseCode {
-        public static final int SERVICE_DISCOVERY_FAILED    =   602;
-        public static final int SERVICE_FOUND               =   603;
-        public static final int SERVICE_LOST                =   604;
-
-        public static final int SERVICE_REGISTRATION_FAILED =   605;
-        public static final int SERVICE_REGISTERED          =   606;
-
-        public static final int SERVICE_RESOLUTION_FAILED   =   607;
-        public static final int SERVICE_RESOLVED            =   608;
-
-        public static final int SERVICE_UPDATED             =   609;
-        public static final int SERVICE_UPDATE_FAILED       =   610;
-
-        public static final int SERVICE_GET_ADDR_FAILED     =   611;
-        public static final int SERVICE_GET_ADDR_SUCCESS    =   612;
-
-        private static final SparseArray<String> CODE_NAMES = new SparseArray<>();
-        static {
-            CODE_NAMES.put(SERVICE_DISCOVERY_FAILED, "SERVICE_DISCOVERY_FAILED");
-            CODE_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
-            CODE_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
-            CODE_NAMES.put(SERVICE_REGISTRATION_FAILED, "SERVICE_REGISTRATION_FAILED");
-            CODE_NAMES.put(SERVICE_REGISTERED, "SERVICE_REGISTERED");
-            CODE_NAMES.put(SERVICE_RESOLUTION_FAILED, "SERVICE_RESOLUTION_FAILED");
-            CODE_NAMES.put(SERVICE_RESOLVED, "SERVICE_RESOLVED");
-            CODE_NAMES.put(SERVICE_UPDATED, "SERVICE_UPDATED");
-            CODE_NAMES.put(SERVICE_UPDATE_FAILED, "SERVICE_UPDATE_FAILED");
-            CODE_NAMES.put(SERVICE_GET_ADDR_FAILED, "SERVICE_GET_ADDR_FAILED");
-            CODE_NAMES.put(SERVICE_GET_ADDR_SUCCESS, "SERVICE_GET_ADDR_SUCCESS");
-        }
-
-        static String nameOf(int code) {
-            String name = CODE_NAMES.get(code);
-            if (name == null) {
-                return Integer.toString(code);
-            }
-            return name;
-        }
-    }
-
-    private class NativeEvent {
-        final int code;
-        final String raw;
-        final String[] cooked;
-
-        NativeEvent(int code, String raw, String[] cooked) {
-            this.code = code;
-            this.raw = raw;
-            this.cooked = cooked;
-        }
-    }
-
-    class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
-        private final CountDownLatch connected = new CountDownLatch(1);
-
-        public void awaitConnection() throws InterruptedException {
-            connected.await();
-        }
-
-        @Override
-        public void onDaemonConnected() {
-            connected.countDown();
-        }
-
-        @Override
-        public boolean onCheckHoldWakeLock(int code) {
-            return false;
-        }
-
-        @Override
-        public boolean onEvent(int code, String raw, String[] cooked) {
-            // TODO: NDC translates a message to a callback, we could enhance NDC to
-            // directly interact with a state machine through messages
-            NativeEvent event = new NativeEvent(code, raw, cooked);
-            mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
-            return true;
-        }
-    }
-
-    interface DaemonConnectionSupplier {
-        DaemonConnection get(NativeCallbackReceiver callback);
-    }
-
-    @VisibleForTesting
-    public static class DaemonConnection {
-        final NativeDaemonConnector mNativeConnector;
-        boolean mIsStarted = false;
-
-        DaemonConnection(NativeCallbackReceiver callback) {
-            mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
-            new Thread(mNativeConnector, MDNS_TAG).start();
-        }
-
-        /**
-         * Executes the specified cmd on the daemon.
-         */
-        public boolean execute(Object... args) {
-            if (DBG) {
-                Log.d(TAG, "mdnssd " + Arrays.toString(args));
-            }
-            try {
-                mNativeConnector.execute("mdnssd", args);
-            } catch (NativeDaemonConnectorException e) {
-                Log.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
-                return false;
-            }
-            return true;
-        }
-
-        /**
-         * Starts the daemon if it is not already started.
-         */
-        public void maybeStart() {
-            if (mIsStarted) {
-                return;
-            }
-            execute("start-service");
-            mIsStarted = true;
-        }
-
-        /**
-         * Stops the daemon if it is started.
-         */
-        public void maybeStop() {
-            if (!mIsStarted) {
-                return;
-            }
-            execute("stop-service");
-            mIsStarted = false;
-        }
-    }
-
-    private boolean registerService(int regId, NsdServiceInfo service) {
-        if (DBG) {
-            Log.d(TAG, "registerService: " + regId + " " + service);
-        }
-        String name = service.getServiceName();
-        String type = service.getServiceType();
-        int port = service.getPort();
-        byte[] textRecord = service.getTxtRecord();
-        String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", "");
-        return mDaemon.execute("register", regId, name, type, port, record);
-    }
-
-    private boolean unregisterService(int regId) {
-        return mDaemon.execute("stop-register", regId);
-    }
-
-    private boolean updateService(int regId, DnsSdTxtRecord t) {
-        if (t == null) {
-            return false;
-        }
-        return mDaemon.execute("update", regId, t.size(), t.getRawData());
-    }
-
-    private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) {
-        final Network network = serviceInfo.getNetwork();
-        final int discoverInterface = getNetworkInterfaceIndex(network);
-        if (network != null && discoverInterface == IFACE_IDX_ANY) {
-            Log.e(TAG, "Interface to discover service on not found");
-            return false;
-        }
-        return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(),
-                discoverInterface);
-    }
-
-    private boolean stopServiceDiscovery(int discoveryId) {
-        return mDaemon.execute("stop-discover", discoveryId);
-    }
-
-    private boolean resolveService(int resolveId, NsdServiceInfo service) {
-        final String name = service.getServiceName();
-        final String type = service.getServiceType();
-        final Network network = service.getNetwork();
-        final int resolveInterface = getNetworkInterfaceIndex(network);
-        if (network != null && resolveInterface == IFACE_IDX_ANY) {
-            Log.e(TAG, "Interface to resolve service on not found");
-            return false;
-        }
-        return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface);
-    }
-
-    /**
-     * Guess the interface to use to resolve or discover a service on a specific network.
-     *
-     * This is an imperfect guess, as for example the network may be gone or not yet fully
-     * registered. This is fine as failing is correct if the network is gone, and a client
-     * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also
-     * this is to support the legacy mdnsresponder implementation, which historically resolved
-     * services on an unspecified network.
-     */
-    private int getNetworkInterfaceIndex(Network network) {
-        if (network == null) return IFACE_IDX_ANY;
-
-        final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
-        if (cm == null) {
-            Log.wtf(TAG, "No ConnectivityManager for resolveService");
-            return IFACE_IDX_ANY;
-        }
-        final LinkProperties lp = cm.getLinkProperties(network);
-        if (lp == null) return IFACE_IDX_ANY;
-
-        // Only resolve on non-stacked interfaces
-        final NetworkInterface iface;
-        try {
-            iface = NetworkInterface.getByName(lp.getInterfaceName());
-        } catch (SocketException e) {
-            Log.e(TAG, "Error querying interface", e);
-            return IFACE_IDX_ANY;
-        }
-
-        if (iface == null) {
-            Log.e(TAG, "Interface not found: " + lp.getInterfaceName());
-            return IFACE_IDX_ANY;
-        }
-
-        return iface.getIndex();
-    }
-
-    private boolean stopResolveService(int resolveId) {
-        return mDaemon.execute("stop-resolve", resolveId);
-    }
-
-    private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) {
-        // interfaceIdx is always obtained (as string) from the service resolved callback
-        return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx);
-    }
-
-    private boolean stopGetAddrInfo(int resolveId) {
-        return mDaemon.execute("stop-getaddrinfo", resolveId);
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
-                != PackageManager.PERMISSION_GRANTED) {
-            pw.println("Permission Denial: can't dump " + TAG
-                    + " due to missing android.permission.DUMP permission");
-            return;
-        }
-
-        for (ClientInfo client : mClients.values()) {
-            pw.println("Client Info");
-            pw.println(client);
-        }
-
-        mNsdStateMachine.dump(fd, pw, args);
-    }
-
-    /* Information tracked per client */
-    private class ClientInfo {
-
-        private static final int MAX_LIMIT = 10;
-        private final INsdManagerCallback mCb;
-        /* Remembers a resolved service until getaddrinfo completes */
-        private NsdServiceInfo mResolvedService;
-
-        /* A map from client id to unique id sent to mDns */
-        private final SparseIntArray mClientIds = new SparseIntArray();
-
-        /* A map from client id to the type of the request we had received */
-        private final SparseIntArray mClientRequests = new SparseIntArray();
-
-        // The target SDK of this client < Build.VERSION_CODES.S
-        private boolean mIsLegacy = false;
-
-        private ClientInfo(INsdManagerCallback cb) {
-            mCb = cb;
-            if (DBG) Log.d(TAG, "New client");
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("mResolvedService ").append(mResolvedService).append("\n");
-            sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
-            for(int i = 0; i< mClientIds.size(); i++) {
-                int clientID = mClientIds.keyAt(i);
-                sb.append("clientId ").append(clientID).
-                    append(" mDnsId ").append(mClientIds.valueAt(i)).
-                    append(" type ").append(mClientRequests.get(clientID)).append("\n");
-            }
-            return sb.toString();
-        }
-
-        private boolean isLegacy() {
-            return mIsLegacy;
-        }
-
-        private void setLegacy() {
-            mIsLegacy = true;
-        }
-
-        // Remove any pending requests from the global map when we get rid of a client,
-        // and send cancellations to the daemon.
-        private void expungeAllRequests() {
-            int globalId, clientId, i;
-            // TODO: to keep handler responsive, do not clean all requests for that client at once.
-            for (i = 0; i < mClientIds.size(); i++) {
-                clientId = mClientIds.keyAt(i);
-                globalId = mClientIds.valueAt(i);
-                mIdToClientInfoMap.remove(globalId);
-                if (DBG) {
-                    Log.d(TAG, "Terminating client-ID " + clientId
-                            + " global-ID " + globalId + " type " + mClientRequests.get(clientId));
-                }
-                switch (mClientRequests.get(clientId)) {
-                    case NsdManager.DISCOVER_SERVICES:
-                        stopServiceDiscovery(globalId);
-                        break;
-                    case NsdManager.RESOLVE_SERVICE:
-                        stopResolveService(globalId);
-                        break;
-                    case NsdManager.REGISTER_SERVICE:
-                        unregisterService(globalId);
-                        break;
-                    default:
-                        break;
-                }
-            }
-            mClientIds.clear();
-            mClientRequests.clear();
-        }
-
-        // mClientIds is a sparse array of listener id -> mDnsClient id.  For a given mDnsClient id,
-        // return the corresponding listener id.  mDnsClient id is also called a global id.
-        private int getClientId(final int globalId) {
-            int idx = mClientIds.indexOfValue(globalId);
-            if (idx < 0) {
-                return idx;
-            }
-            return mClientIds.keyAt(idx);
-        }
-
-        void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
-            try {
-                mCb.onDiscoverServicesStarted(listenerKey, info);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onDiscoverServicesStarted", e);
-            }
-        }
-
-        void onDiscoverServicesFailed(int listenerKey, int error) {
-            try {
-                mCb.onDiscoverServicesFailed(listenerKey, error);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onDiscoverServicesFailed", e);
-            }
-        }
-
-        void onServiceFound(int listenerKey, NsdServiceInfo info) {
-            try {
-                mCb.onServiceFound(listenerKey, info);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onServiceFound(", e);
-            }
-        }
-
-        void onServiceLost(int listenerKey, NsdServiceInfo info) {
-            try {
-                mCb.onServiceLost(listenerKey, info);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onServiceLost(", e);
-            }
-        }
-
-        void onStopDiscoveryFailed(int listenerKey, int error) {
-            try {
-                mCb.onStopDiscoveryFailed(listenerKey, error);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onStopDiscoveryFailed", e);
-            }
-        }
-
-        void onStopDiscoverySucceeded(int listenerKey) {
-            try {
-                mCb.onStopDiscoverySucceeded(listenerKey);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onStopDiscoverySucceeded", e);
-            }
-        }
-
-        void onRegisterServiceFailed(int listenerKey, int error) {
-            try {
-                mCb.onRegisterServiceFailed(listenerKey, error);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onRegisterServiceFailed", e);
-            }
-        }
-
-        void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
-            try {
-                mCb.onRegisterServiceSucceeded(listenerKey, info);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onRegisterServiceSucceeded", e);
-            }
-        }
-
-        void onUnregisterServiceFailed(int listenerKey, int error) {
-            try {
-                mCb.onUnregisterServiceFailed(listenerKey, error);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onUnregisterServiceFailed", e);
-            }
-        }
-
-        void onUnregisterServiceSucceeded(int listenerKey) {
-            try {
-                mCb.onUnregisterServiceSucceeded(listenerKey);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onUnregisterServiceSucceeded", e);
-            }
-        }
-
-        void onResolveServiceFailed(int listenerKey, int error) {
-            try {
-                mCb.onResolveServiceFailed(listenerKey, error);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onResolveServiceFailed", e);
-            }
-        }
-
-        void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
-            try {
-                mCb.onResolveServiceSucceeded(listenerKey, info);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error calling onResolveServiceSucceeded", e);
-            }
-        }
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
deleted file mode 100644
index 25c88eb..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.
- */
-package com.android.server.net;
-
-import android.content.Context;
-import android.net.INetd;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.ErrnoException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
-import com.android.net.module.util.BpfMap;
-import com.android.net.module.util.IBpfMap;
-import com.android.net.module.util.InterfaceParams;
-import com.android.net.module.util.Struct.U32;
-
-/**
- * Monitor interface added (without removed) and right interface name and its index to bpf map.
- */
-public class BpfInterfaceMapUpdater {
-    private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName();
-    // This is current path but may be changed soon.
-    private static final String IFACE_INDEX_NAME_MAP_PATH =
-            "/sys/fs/bpf/map_netd_iface_index_name_map";
-    private final IBpfMap<U32, InterfaceMapValue> mBpfMap;
-    private final INetd mNetd;
-    private final Handler mHandler;
-    private final Dependencies mDeps;
-
-    public BpfInterfaceMapUpdater(Context ctx, Handler handler) {
-        this(ctx, handler, new Dependencies());
-    }
-
-    @VisibleForTesting
-    public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) {
-        mDeps = deps;
-        mBpfMap = deps.getInterfaceMap();
-        mNetd = deps.getINetd(ctx);
-        mHandler = handler;
-    }
-
-    /**
-     * Dependencies of BpfInerfaceMapUpdater, for injection in tests.
-     */
-    @VisibleForTesting
-    public static class Dependencies {
-        /** Create BpfMap for updating interface and index mapping. */
-        public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() {
-            try {
-                return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR,
-                    U32.class, InterfaceMapValue.class);
-            } catch (ErrnoException e) {
-                Log.e(TAG, "Cannot create interface map: " + e);
-                return null;
-            }
-        }
-
-        /** Get InterfaceParams for giving interface name. */
-        public InterfaceParams getInterfaceParams(String ifaceName) {
-            return InterfaceParams.getByName(ifaceName);
-        }
-
-        /** Get INetd binder object. */
-        public INetd getINetd(Context ctx) {
-            return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE));
-        }
-    }
-
-    /**
-     * Start listening interface update event.
-     * Query current interface names before listening.
-     */
-    public void start() {
-        mHandler.post(() -> {
-            if (mBpfMap == null) {
-                Log.wtf(TAG, "Fail to start: Null bpf map");
-                return;
-            }
-
-            try {
-                // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead.
-                mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver());
-            } catch (RemoteException e) {
-                Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e);
-            }
-
-            final String[] ifaces;
-            try {
-                // TODO: use a netlink dump to get the current interface list.
-                ifaces = mNetd.interfaceGetList();
-            } catch (RemoteException | ServiceSpecificException e) {
-                Log.wtf(TAG, "Unable to query interface names by netd, " + e);
-                return;
-            }
-
-            for (String ifaceName : ifaces) {
-                addInterface(ifaceName);
-            }
-        });
-    }
-
-    private void addInterface(String ifaceName) {
-        final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName);
-        if (iface == null) {
-            Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName);
-            return;
-        }
-
-        try {
-            mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName));
-        } catch (ErrnoException e) {
-            Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e);
-        }
-    }
-
-    private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener {
-        @Override
-        public void onInterfaceAdded(String ifName) {
-            mHandler.post(() -> addInterface(ifName));
-        }
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
deleted file mode 100644
index 443e5b3..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for cookie tag map.
- */
-public class CookieTagMapKey extends Struct {
-    @Field(order = 0, type = Type.S64)
-    public final long socketCookie;
-
-    public CookieTagMapKey(final long socketCookie) {
-        this.socketCookie = socketCookie;
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
deleted file mode 100644
index 93b9195..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Value for cookie tag map.
- */
-public class CookieTagMapValue extends Struct {
-    @Field(order = 0, type = Type.U32)
-    public final long uid;
-
-    @Field(order = 1, type = Type.U32)
-    public final long tag;
-
-    public CookieTagMapValue(final long uid, final long tag) {
-        this.uid = uid;
-        this.tag = tag;
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
deleted file mode 100644
index 35dc455..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.BufferedOutputStream;
-import java.io.DataOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * This class provides APIs to do a delayed data write to a given {@link OutputStream}.
- */
-public class DelayedDiskWrite {
-    private static final String TAG = "DelayedDiskWrite";
-
-    private HandlerThread mDiskWriteHandlerThread;
-    private Handler mDiskWriteHandler;
-    /* Tracks multiple writes on the same thread */
-    private int mWriteSequence = 0;
-
-    /**
-     * Used to do a delayed data write to a given {@link OutputStream}.
-     */
-    public interface Writer {
-        /**
-         * write data to a given {@link OutputStream}.
-         */
-        void onWriteCalled(DataOutputStream out) throws IOException;
-    }
-
-    /**
-     * Do a delayed data write to a given output stream opened from filePath.
-     */
-    public void write(final String filePath, final Writer w) {
-        write(filePath, w, true);
-    }
-
-    /**
-     * Do a delayed data write to a given output stream opened from filePath.
-     */
-    public void write(final String filePath, final Writer w, final boolean open) {
-        if (TextUtils.isEmpty(filePath)) {
-            throw new IllegalArgumentException("empty file path");
-        }
-
-        /* Do a delayed write to disk on a separate handler thread */
-        synchronized (this) {
-            if (++mWriteSequence == 1) {
-                mDiskWriteHandlerThread = new HandlerThread("DelayedDiskWriteThread");
-                mDiskWriteHandlerThread.start();
-                mDiskWriteHandler = new Handler(mDiskWriteHandlerThread.getLooper());
-            }
-        }
-
-        mDiskWriteHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                doWrite(filePath, w, open);
-            }
-        });
-    }
-
-    private void doWrite(String filePath, Writer w, boolean open) {
-        DataOutputStream out = null;
-        try {
-            if (open) {
-                out = new DataOutputStream(new BufferedOutputStream(
-                        new FileOutputStream(filePath)));
-            }
-            w.onWriteCalled(out);
-        } catch (IOException e) {
-            loge("Error writing data file " + filePath);
-        } finally {
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (Exception e) { }
-            }
-
-            // Quit if no more writes sent
-            synchronized (this) {
-                if (--mWriteSequence == 0) {
-                    mDiskWriteHandler.getLooper().quit();
-                    mDiskWriteHandler = null;
-                    mDiskWriteHandlerThread = null;
-                }
-            }
-        }
-    }
-
-    private void loge(String s) {
-        Log.e(TAG, s);
-    }
-}
-
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
deleted file mode 100644
index 42c0044..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.
- */
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * The value of bpf interface index map which is used for NetworkStatsService.
- */
-public class InterfaceMapValue extends Struct {
-    @Field(order = 0, type = Type.ByteArray, arraysize = 16)
-    public final byte[] interfaceName;
-
-    public InterfaceMapValue(String iface) {
-        final byte[] ifaceArray = iface.getBytes();
-        interfaceName = new byte[16];
-        // All array bytes after the interface name, if any, must be 0.
-        System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length);
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java b/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
deleted file mode 100644
index 3a9a544..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/IpConfigStore.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import android.net.InetAddresses;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.ProxyInfo;
-import android.net.StaticIpConfiguration;
-import android.net.Uri;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.ProxyUtils;
-
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-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;
-
-    protected final DelayedDiskWrite mWriter;
-
-    /* IP and proxy configuration keys */
-    protected static final String ID_KEY = "id";
-    protected static final String IP_ASSIGNMENT_KEY = "ipAssignment";
-    protected static final String LINK_ADDRESS_KEY = "linkAddress";
-    protected static final String GATEWAY_KEY = "gateway";
-    protected static final String DNS_KEY = "dns";
-    protected static final String PROXY_SETTINGS_KEY = "proxySettings";
-    protected static final String PROXY_HOST_KEY = "proxyHost";
-    protected static final String PROXY_PORT_KEY = "proxyPort";
-    protected static final String PROXY_PAC_FILE = "proxyPac";
-    protected static final String EXCLUSION_LIST_KEY = "exclusionList";
-    protected static final String EOS = "eos";
-
-    protected static final int IPCONFIG_FILE_VERSION = 3;
-
-    public IpConfigStore(DelayedDiskWrite writer) {
-        mWriter = writer;
-    }
-
-    public IpConfigStore() {
-        this(new DelayedDiskWrite());
-    }
-
-    private static boolean writeConfig(DataOutputStream out, String configKey,
-            IpConfiguration config) throws IOException {
-        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 {
-        boolean written = false;
-
-        try {
-            switch (config.getIpAssignment()) {
-                case STATIC:
-                    out.writeUTF(IP_ASSIGNMENT_KEY);
-                    out.writeUTF(config.getIpAssignment().toString());
-                    StaticIpConfiguration staticIpConfiguration = config.getStaticIpConfiguration();
-                    if (staticIpConfiguration != null) {
-                        if (staticIpConfiguration.getIpAddress() != null) {
-                            LinkAddress ipAddress = staticIpConfiguration.getIpAddress();
-                            out.writeUTF(LINK_ADDRESS_KEY);
-                            out.writeUTF(ipAddress.getAddress().getHostAddress());
-                            out.writeInt(ipAddress.getPrefixLength());
-                        }
-                        if (staticIpConfiguration.getGateway() != null) {
-                            out.writeUTF(GATEWAY_KEY);
-                            out.writeInt(0);  // Default route.
-                            out.writeInt(1);  // Have a gateway.
-                            out.writeUTF(staticIpConfiguration.getGateway().getHostAddress());
-                        }
-                        for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) {
-                            out.writeUTF(DNS_KEY);
-                            out.writeUTF(inetAddr.getHostAddress());
-                        }
-                    }
-                    written = true;
-                    break;
-                case DHCP:
-                    out.writeUTF(IP_ASSIGNMENT_KEY);
-                    out.writeUTF(config.getIpAssignment().toString());
-                    written = true;
-                    break;
-                case UNASSIGNED:
-                /* Ignore */
-                    break;
-                default:
-                    loge("Ignore invalid ip assignment while writing");
-                    break;
-            }
-
-            switch (config.getProxySettings()) {
-                case STATIC:
-                    ProxyInfo proxyProperties = config.getHttpProxy();
-                    String exclusionList = ProxyUtils.exclusionListAsString(
-                            proxyProperties.getExclusionList());
-                    out.writeUTF(PROXY_SETTINGS_KEY);
-                    out.writeUTF(config.getProxySettings().toString());
-                    out.writeUTF(PROXY_HOST_KEY);
-                    out.writeUTF(proxyProperties.getHost());
-                    out.writeUTF(PROXY_PORT_KEY);
-                    out.writeInt(proxyProperties.getPort());
-                    if (exclusionList != null) {
-                        out.writeUTF(EXCLUSION_LIST_KEY);
-                        out.writeUTF(exclusionList);
-                    }
-                    written = true;
-                    break;
-                case PAC:
-                    ProxyInfo proxyPacProperties = config.getHttpProxy();
-                    out.writeUTF(PROXY_SETTINGS_KEY);
-                    out.writeUTF(config.getProxySettings().toString());
-                    out.writeUTF(PROXY_PAC_FILE);
-                    out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
-                    written = true;
-                    break;
-                case NONE:
-                    out.writeUTF(PROXY_SETTINGS_KEY);
-                    out.writeUTF(config.getProxySettings().toString());
-                    written = true;
-                    break;
-                case UNASSIGNED:
-                    /* Ignore */
-                    break;
-                default:
-                    loge("Ignore invalid proxy settings while writing");
-                    break;
-            }
-
-            if (written) {
-                out.writeUTF(ID_KEY);
-                if (version < 3) {
-                    out.writeInt(Integer.valueOf(configKey));
-                } else {
-                    out.writeUTF(configKey);
-                }
-            }
-        } catch (NullPointerException e) {
-            loge("Failure in writing " + config + e);
-        }
-        out.writeUTF(EOS);
-
-        return written;
-    }
-
-    /**
-     * @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.
-     */
-    @Deprecated
-    public void writeIpAndProxyConfigurationsToFile(String filePath,
-                                              final SparseArray<IpConfiguration> networks) {
-        mWriter.write(filePath, out -> {
-            out.writeInt(IPCONFIG_FILE_VERSION);
-            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++) {
-                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 {
-            bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
-        } catch (FileNotFoundException e) {
-            // Return an empty array here because callers expect an empty array when the file is
-            // not present.
-            loge("Error opening configuration file: " + e);
-            return new ArrayMap<>(0);
-        }
-        return readIpConfigurations(bufferedInputStream);
-    }
-
-    /** @deprecated use {@link #readIpConfigurations(String)} */
-    @Deprecated
-    public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(String filePath) {
-        BufferedInputStream bufferedInputStream;
-        try {
-            bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
-        } catch (FileNotFoundException e) {
-            // Return an empty array here because callers expect an empty array when the file is
-            // not present.
-            loge("Error opening configuration file: " + e);
-            return new SparseArray<>();
-        }
-        return readIpAndProxyConfigurations(bufferedInputStream);
-    }
-
-    /** @deprecated use {@link #readIpConfigurations(InputStream)} */
-    @Deprecated
-    public static SparseArray<IpConfiguration> readIpAndProxyConfigurations(
-            InputStream inputStream) {
-        ArrayMap<String, IpConfiguration> networks = readIpConfigurations(inputStream);
-        if (networks == null) {
-            return null;
-        }
-
-        SparseArray<IpConfiguration> networksById = new SparseArray<>();
-        for (int i = 0; i < networks.size(); i++) {
-            int id = Integer.valueOf(networks.keyAt(i));
-            networksById.put(id, networks.valueAt(i));
-        }
-
-        return networksById;
-    }
-
-    /** Returns a map of network identity token and {@link IpConfiguration}. */
-    public static ArrayMap<String, IpConfiguration> readIpConfigurations(
-            InputStream inputStream) {
-        ArrayMap<String, IpConfiguration> networks = new ArrayMap<>();
-        DataInputStream in = null;
-        try {
-            in = new DataInputStream(inputStream);
-
-            int version = in.readInt();
-            if (version != 3 && version != 2 && version != 1) {
-                loge("Bad version on IP configuration file, ignore read");
-                return null;
-            }
-
-            while (true) {
-                String uniqueToken = null;
-                // Default is DHCP with no proxy
-                IpAssignment ipAssignment = IpAssignment.DHCP;
-                ProxySettings proxySettings = ProxySettings.NONE;
-                StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
-                LinkAddress linkAddress = null;
-                InetAddress gatewayAddress = null;
-                String proxyHost = null;
-                String pacFileUrl = null;
-                int proxyPort = -1;
-                String exclusionList = null;
-                String key;
-                final List<InetAddress> dnsServers = new ArrayList<>();
-
-                do {
-                    key = in.readUTF();
-                    try {
-                        if (key.equals(ID_KEY)) {
-                            if (version < 3) {
-                                int id = in.readInt();
-                                uniqueToken = String.valueOf(id);
-                            } else {
-                                uniqueToken = in.readUTF();
-                            }
-                        } else if (key.equals(IP_ASSIGNMENT_KEY)) {
-                            ipAssignment = IpAssignment.valueOf(in.readUTF());
-                        } else if (key.equals(LINK_ADDRESS_KEY)) {
-                            LinkAddress parsedLinkAddress =
-                                    new LinkAddress(
-                                            InetAddresses.parseNumericAddress(in.readUTF()),
-                                            in.readInt());
-                            if (parsedLinkAddress.getAddress() instanceof Inet4Address
-                                    && linkAddress == null) {
-                                linkAddress = parsedLinkAddress;
-                            } else {
-                                loge("Non-IPv4 or duplicate address: " + parsedLinkAddress);
-                            }
-                        } else if (key.equals(GATEWAY_KEY)) {
-                            LinkAddress dest = null;
-                            InetAddress gateway = null;
-                            if (version == 1) {
-                                // only supported default gateways - leave the dest/prefix empty
-                                gateway = InetAddresses.parseNumericAddress(in.readUTF());
-                                if (gatewayAddress == null) {
-                                    gatewayAddress = gateway;
-                                } else {
-                                    loge("Duplicate gateway: " + gateway.getHostAddress());
-                                }
-                            } else {
-                                if (in.readInt() == 1) {
-                                    dest =
-                                            new LinkAddress(
-                                                    InetAddresses.parseNumericAddress(in.readUTF()),
-                                                    in.readInt());
-                                }
-                                if (in.readInt() == 1) {
-                                    gateway = InetAddresses.parseNumericAddress(in.readUTF());
-                                }
-                                // If the destination is a default IPv4 route, use the gateway
-                                // address unless already set. If there is no destination, assume
-                                // it is default route and use the gateway address in all cases.
-                                if (dest == null) {
-                                    gatewayAddress = gateway;
-                                } else if (dest.getAddress() instanceof Inet4Address
-                                        && dest.getPrefixLength() == 0 && gatewayAddress == null) {
-                                    gatewayAddress = gateway;
-                                } else {
-                                    loge("Non-IPv4 default or duplicate route: "
-                                            + dest.getAddress());
-                                }
-                            }
-                        } else if (key.equals(DNS_KEY)) {
-                            dnsServers.add(InetAddresses.parseNumericAddress(in.readUTF()));
-                        } else if (key.equals(PROXY_SETTINGS_KEY)) {
-                            proxySettings = ProxySettings.valueOf(in.readUTF());
-                        } else if (key.equals(PROXY_HOST_KEY)) {
-                            proxyHost = in.readUTF();
-                        } else if (key.equals(PROXY_PORT_KEY)) {
-                            proxyPort = in.readInt();
-                        } else if (key.equals(PROXY_PAC_FILE)) {
-                            pacFileUrl = in.readUTF();
-                        } else if (key.equals(EXCLUSION_LIST_KEY)) {
-                            exclusionList = in.readUTF();
-                        } else if (key.equals(EOS)) {
-                            break;
-                        } else {
-                            loge("Ignore unknown key " + key + "while reading");
-                        }
-                    } catch (IllegalArgumentException e) {
-                        loge("Ignore invalid address while reading" + e);
-                    }
-                } while (true);
-
-                staticIpConfiguration = new StaticIpConfiguration.Builder()
-                    .setIpAddress(linkAddress)
-                    .setGateway(gatewayAddress)
-                    .setDnsServers(dnsServers)
-                    .build();
-
-                if (uniqueToken != null) {
-                    IpConfiguration config = new IpConfiguration();
-                    networks.put(uniqueToken, config);
-
-                    switch (ipAssignment) {
-                        case STATIC:
-                            config.setStaticIpConfiguration(staticIpConfiguration);
-                            config.setIpAssignment(ipAssignment);
-                            break;
-                        case DHCP:
-                            config.setIpAssignment(ipAssignment);
-                            break;
-                        case UNASSIGNED:
-                            loge("BUG: Found UNASSIGNED IP on file, use DHCP");
-                            config.setIpAssignment(IpAssignment.DHCP);
-                            break;
-                        default:
-                            loge("Ignore invalid ip assignment while reading.");
-                            config.setIpAssignment(IpAssignment.UNASSIGNED);
-                            break;
-                    }
-
-                    switch (proxySettings) {
-                        case STATIC:
-                            ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(proxyHost, proxyPort,
-                                    ProxyUtils.exclusionStringAsList(exclusionList));
-                            config.setProxySettings(proxySettings);
-                            config.setHttpProxy(proxyInfo);
-                            break;
-                        case PAC:
-                            ProxyInfo proxyPacProperties =
-                                    ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl));
-                            config.setProxySettings(proxySettings);
-                            config.setHttpProxy(proxyPacProperties);
-                            break;
-                        case NONE:
-                            config.setProxySettings(proxySettings);
-                            break;
-                        case UNASSIGNED:
-                            loge("BUG: Found UNASSIGNED proxy on file, use NONE");
-                            config.setProxySettings(ProxySettings.NONE);
-                            break;
-                        default:
-                            loge("Ignore invalid proxy settings while reading");
-                            config.setProxySettings(ProxySettings.UNASSIGNED);
-                            break;
-                    }
-                } else {
-                    if (DBG) log("Missing id while parsing configuration");
-                }
-            }
-        } catch (EOFException ignore) {
-        } catch (IOException e) {
-            loge("Error parsing configuration: " + e);
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (Exception e) { }
-            }
-        }
-
-        return networks;
-    }
-
-    protected static void loge(String s) {
-        Log.e(TAG, s);
-    }
-
-    protected static void log(String s) {
-        Log.d(TAG, s);
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
deleted file mode 100644
index 3b93f1a..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.net.NetworkStats.INTERFACES_ALL;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.TAG_ALL;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.net.NetworkStats;
-import android.net.UnderlyingNetworkInfo;
-import android.os.ServiceSpecificException;
-import android.os.StrictMode;
-import android.os.SystemClock;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ProcFileReader;
-import com.android.net.module.util.CollectionUtils;
-import com.android.server.BpfNetMaps;
-
-import libcore.io.IoUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.ProtocolException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
- * files as needed.
- *
- * @hide
- */
-public class NetworkStatsFactory {
-    static {
-        System.loadLibrary("service-connectivity");
-    }
-
-    private static final String TAG = "NetworkStatsFactory";
-
-    private static final boolean USE_NATIVE_PARSING = true;
-    private static final boolean VALIDATE_NATIVE_STATS = false;
-
-    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
-    private final File mStatsXtIfaceAll;
-    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
-    private final File mStatsXtIfaceFmt;
-    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
-    private final File mStatsXtUid;
-
-    private final boolean mUseBpfStats;
-
-    private final Context mContext;
-
-    private final BpfNetMaps mBpfNetMaps;
-
-    /**
-     * Guards persistent data access in this class
-     *
-     * <p>In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out
-     * to other code that will acquire other locks within the system server. See b/134244752.
-     */
-    private final Object mPersistentDataLock = new Object();
-
-    /** Set containing info about active VPNs and their underlying networks. */
-    private volatile UnderlyingNetworkInfo[] mUnderlyingNetworkInfos = new UnderlyingNetworkInfo[0];
-
-    // A persistent snapshot of cumulative stats since device start
-    @GuardedBy("mPersistentDataLock")
-    private NetworkStats mPersistSnapshot;
-
-    // The persistent snapshot of tun and 464xlat adjusted stats since device start
-    @GuardedBy("mPersistentDataLock")
-    private NetworkStats mTunAnd464xlatAdjustedStats;
-
-    /**
-     * (Stacked interface) -> (base interface) association for all connected ifaces since boot.
-     *
-     * Because counters must never roll backwards, once a given interface is stacked on top of an
-     * underlying interface, the stacked interface can never be stacked on top of
-     * another interface. */
-    private final ConcurrentHashMap<String, String> mStackedIfaces
-            = new ConcurrentHashMap<>();
-
-    /** Informs the factory of a new stacked interface. */
-    public void noteStackedIface(String stackedIface, String baseIface) {
-        if (stackedIface != null && baseIface != null) {
-            mStackedIfaces.put(stackedIface, baseIface);
-        }
-    }
-
-    /**
-     * Set active VPN information for data usage migration purposes
-     *
-     * <p>Traffic on TUN-based VPNs inherently all appear to be originated from the VPN providing
-     * app's UID. This method is used to support migration of VPN data usage, ensuring data is
-     * accurately billed to the real owner of the traffic.
-     *
-     * @param vpnArray The snapshot of the currently-running VPNs.
-     */
-    public void updateUnderlyingNetworkInfos(UnderlyingNetworkInfo[] vpnArray) {
-        mUnderlyingNetworkInfos = vpnArray.clone();
-    }
-
-    /**
-     * Get a set of interfaces containing specified ifaces and stacked interfaces.
-     *
-     * <p>The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces
-     * on which the specified ones are stacked. Stacked interfaces are those noted with
-     * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method
-     * is called are guaranteed to be included.
-     */
-    public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) {
-        if (requiredIfaces == NetworkStats.INTERFACES_ALL) {
-            return null;
-        }
-
-        HashSet<String> relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces));
-        // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse
-        // elements as they existed upon construction exactly once, and may
-        // (but are not guaranteed to) reflect any modifications subsequent to construction".
-        // This is enough here.
-        for (Map.Entry<String, String> entry : mStackedIfaces.entrySet()) {
-            if (relatedIfaces.contains(entry.getKey())) {
-                relatedIfaces.add(entry.getValue());
-            } else if (relatedIfaces.contains(entry.getValue())) {
-                relatedIfaces.add(entry.getKey());
-            }
-        }
-
-        String[] outArray = new String[relatedIfaces.size()];
-        return relatedIfaces.toArray(outArray);
-    }
-
-    /**
-     * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
-     * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
-     */
-    public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic) {
-        NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
-    }
-
-    public NetworkStatsFactory(@NonNull Context ctx) {
-        this(ctx, new File("/proc/"), true);
-    }
-
-    @VisibleForTesting
-    public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) {
-        mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
-        mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
-        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
-        mUseBpfStats = useBpfStats;
-        mBpfNetMaps = new BpfNetMaps();
-        synchronized (mPersistentDataLock) {
-            mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
-            mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
-        }
-        mContext = ctx;
-    }
-
-    public NetworkStats readBpfNetworkStatsDev() throws IOException {
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
-        if (nativeReadNetworkStatsDev(stats) != 0) {
-            throw new IOException("Failed to parse bpf iface stats");
-        }
-        return stats;
-    }
-
-    /**
-     * Parse and return interface-level summary {@link NetworkStats} measured
-     * using {@code /proc/net/dev} style hooks, which may include non IP layer
-     * traffic. Values monotonically increase since device boot, and may include
-     * details about inactive interfaces.
-     *
-     * @throws IllegalStateException when problem parsing stats.
-     */
-    public NetworkStats readNetworkStatsSummaryDev() throws IOException {
-
-        // Return xt_bpf stats if switched to bpf module.
-        if (mUseBpfStats)
-            return readBpfNetworkStatsDev();
-
-        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-
-        ProcFileReader reader = null;
-        try {
-            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceAll));
-
-            while (reader.hasMoreData()) {
-                entry.iface = reader.nextString();
-                entry.uid = UID_ALL;
-                entry.set = SET_ALL;
-                entry.tag = TAG_NONE;
-
-                final boolean active = reader.nextInt() != 0;
-
-                // always include snapshot values
-                entry.rxBytes = reader.nextLong();
-                entry.rxPackets = reader.nextLong();
-                entry.txBytes = reader.nextLong();
-                entry.txPackets = reader.nextLong();
-
-                // fold in active numbers, but only when active
-                if (active) {
-                    entry.rxBytes += reader.nextLong();
-                    entry.rxPackets += reader.nextLong();
-                    entry.txBytes += reader.nextLong();
-                    entry.txPackets += reader.nextLong();
-                }
-
-                stats.insertEntry(entry);
-                reader.finishLine();
-            }
-        } catch (NullPointerException|NumberFormatException e) {
-            throw protocolExceptionWithCause("problem parsing stats", e);
-        } finally {
-            IoUtils.closeQuietly(reader);
-            StrictMode.setThreadPolicy(savedPolicy);
-        }
-        return stats;
-    }
-
-    /**
-     * Parse and return interface-level summary {@link NetworkStats}. Designed
-     * to return only IP layer traffic. Values monotonically increase since
-     * device boot, and may include details about inactive interfaces.
-     *
-     * @throws IllegalStateException when problem parsing stats.
-     */
-    public NetworkStats readNetworkStatsSummaryXt() throws IOException {
-
-        // Return xt_bpf stats if qtaguid  module is replaced.
-        if (mUseBpfStats)
-            return readBpfNetworkStatsDev();
-
-        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
-        // return null when kernel doesn't support
-        if (!mStatsXtIfaceFmt.exists()) return null;
-
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-
-        ProcFileReader reader = null;
-        try {
-            // open and consume header line
-            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceFmt));
-            reader.finishLine();
-
-            while (reader.hasMoreData()) {
-                entry.iface = reader.nextString();
-                entry.uid = UID_ALL;
-                entry.set = SET_ALL;
-                entry.tag = TAG_NONE;
-
-                entry.rxBytes = reader.nextLong();
-                entry.rxPackets = reader.nextLong();
-                entry.txBytes = reader.nextLong();
-                entry.txPackets = reader.nextLong();
-
-                stats.insertEntry(entry);
-                reader.finishLine();
-            }
-        } catch (NullPointerException|NumberFormatException e) {
-            throw protocolExceptionWithCause("problem parsing stats", e);
-        } finally {
-            IoUtils.closeQuietly(reader);
-            StrictMode.setThreadPolicy(savedPolicy);
-        }
-        return stats;
-    }
-
-    public NetworkStats readNetworkStatsDetail() throws IOException {
-        return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL);
-    }
-
-    @GuardedBy("mPersistentDataLock")
-    private void requestSwapActiveStatsMapLocked() throws IOException {
-        try {
-            // Do a active map stats swap. Once the swap completes, this code
-            // can read and clean the inactive map without races.
-            mBpfNetMaps.swapActiveStatsMap();
-        } catch (ServiceSpecificException e) {
-            throw new IOException(e);
-        }
-    }
-
-    /**
-     * Reads the detailed UID stats based on the provided parameters
-     *
-     * @param limitUid the UID to limit this query to
-     * @param limitIfaces the interfaces to limit this query to. Use {@link
-     *     NetworkStats.INTERFACES_ALL} to select all interfaces
-     * @param limitTag the tags to limit this query to
-     * @return the NetworkStats instance containing network statistics at the present time.
-     */
-    public NetworkStats readNetworkStatsDetail(
-            int limitUid, String[] limitIfaces, int limitTag) throws IOException {
-        // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other
-        // code that will acquire other locks within the system server. See b/134244752.
-        synchronized (mPersistentDataLock) {
-            // Take a reference. If this gets swapped out, we still have the old reference.
-            final UnderlyingNetworkInfo[] vpnArray = mUnderlyingNetworkInfos;
-            // Take a defensive copy. mPersistSnapshot is mutated in some cases below
-            final NetworkStats prev = mPersistSnapshot.clone();
-
-            if (USE_NATIVE_PARSING) {
-                final NetworkStats stats =
-                        new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */);
-                if (mUseBpfStats) {
-                    requestSwapActiveStatsMapLocked();
-                    // Stats are always read from the inactive map, so they must be read after the
-                    // swap
-                    if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
-                            INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
-                        throw new IOException("Failed to parse network stats");
-                    }
-
-                    // BPF stats are incremental; fold into mPersistSnapshot.
-                    mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
-                    mPersistSnapshot.combineAllValues(stats);
-                } else {
-                    if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
-                            INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
-                        throw new IOException("Failed to parse network stats");
-                    }
-                    if (VALIDATE_NATIVE_STATS) {
-                        final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid,
-                                UID_ALL, INTERFACES_ALL, TAG_ALL);
-                        assertEquals(javaStats, stats);
-                    }
-
-                    mPersistSnapshot = stats;
-                }
-            } else {
-                mPersistSnapshot = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL,
-                        TAG_ALL);
-            }
-
-            NetworkStats adjustedStats = adjustForTunAnd464Xlat(mPersistSnapshot, prev, vpnArray);
-
-            // Filter return values
-            adjustedStats.filter(limitUid, limitIfaces, limitTag);
-            return adjustedStats;
-        }
-    }
-
-    @GuardedBy("mPersistentDataLock")
-    private NetworkStats adjustForTunAnd464Xlat(NetworkStats uidDetailStats,
-            NetworkStats previousStats, UnderlyingNetworkInfo[] vpnArray) {
-        // Calculate delta from last snapshot
-        final NetworkStats delta = uidDetailStats.subtract(previousStats);
-
-        // Apply 464xlat adjustments before VPN adjustments. If VPNs are using v4 on a v6 only
-        // network, the overhead is their fault.
-        // No locking here: apply464xlatAdjustments behaves fine with an add-only
-        // ConcurrentHashMap.
-        delta.apply464xlatAdjustments(mStackedIfaces);
-
-        // Migrate data usage over a VPN to the TUN network.
-        for (UnderlyingNetworkInfo info : vpnArray) {
-            delta.migrateTun(info.getOwnerUid(), info.getInterface(),
-                    info.getUnderlyingInterfaces());
-            // Filter out debug entries as that may lead to over counting.
-            delta.filterDebugEntries();
-        }
-
-        // Update mTunAnd464xlatAdjustedStats with migrated delta.
-        mTunAnd464xlatAdjustedStats.combineAllValues(delta);
-        mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
-
-        return mTunAnd464xlatAdjustedStats.clone();
-    }
-
-    /**
-     * Parse and return {@link NetworkStats} with UID-level details. Values are
-     * expected to monotonically increase since device boot.
-     */
-    @VisibleForTesting
-    public static NetworkStats javaReadNetworkStatsDetail(File detailPath, int limitUid,
-            String[] limitIfaces, int limitTag)
-            throws IOException {
-        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-
-        int idx = 1;
-        int lastIdx = 1;
-
-        ProcFileReader reader = null;
-        try {
-            // open and consume header line
-            reader = new ProcFileReader(new FileInputStream(detailPath));
-            reader.finishLine();
-
-            while (reader.hasMoreData()) {
-                idx = reader.nextInt();
-                if (idx != lastIdx + 1) {
-                    throw new ProtocolException(
-                            "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
-                }
-                lastIdx = idx;
-
-                entry.iface = reader.nextString();
-                entry.tag = kernelToTag(reader.nextString());
-                entry.uid = reader.nextInt();
-                entry.set = reader.nextInt();
-                entry.rxBytes = reader.nextLong();
-                entry.rxPackets = reader.nextLong();
-                entry.txBytes = reader.nextLong();
-                entry.txPackets = reader.nextLong();
-
-                if ((limitIfaces == null || CollectionUtils.contains(limitIfaces, entry.iface))
-                        && (limitUid == UID_ALL || limitUid == entry.uid)
-                        && (limitTag == TAG_ALL || limitTag == entry.tag)) {
-                    stats.insertEntry(entry);
-                }
-
-                reader.finishLine();
-            }
-        } catch (NullPointerException|NumberFormatException e) {
-            throw protocolExceptionWithCause("problem parsing idx " + idx, e);
-        } finally {
-            IoUtils.closeQuietly(reader);
-            StrictMode.setThreadPolicy(savedPolicy);
-        }
-
-        return stats;
-    }
-
-    public void assertEquals(NetworkStats expected, NetworkStats actual) {
-        if (expected.size() != actual.size()) {
-            throw new AssertionError(
-                    "Expected size " + expected.size() + ", actual size " + actual.size());
-        }
-
-        NetworkStats.Entry expectedRow = null;
-        NetworkStats.Entry actualRow = null;
-        for (int i = 0; i < expected.size(); i++) {
-            expectedRow = expected.getValues(i, expectedRow);
-            actualRow = actual.getValues(i, actualRow);
-            if (!expectedRow.equals(actualRow)) {
-                throw new AssertionError(
-                        "Expected row " + i + ": " + expectedRow + ", actual row " + actualRow);
-            }
-        }
-    }
-
-    /**
-     * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
-     * format like {@code 0x7fffffff00000000}.
-     */
-    public static int kernelToTag(String string) {
-        int length = string.length();
-        if (length > 10) {
-            return Long.decode(string.substring(0, length - 8)).intValue();
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * Parse statistics from file into given {@link NetworkStats} object. Values
-     * are expected to monotonically increase since device boot.
-     */
-    @VisibleForTesting
-    public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
-        int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
-
-    @VisibleForTesting
-    public static native int nativeReadNetworkStatsDev(NetworkStats stats);
-
-    private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) {
-        ProtocolException pe = new ProtocolException(message);
-        pe.initCause(cause);
-        return pe;
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
deleted file mode 100644
index fdfc893..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
-
-import android.app.usage.NetworkStatsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.DataUsageRequest;
-import android.net.NetworkIdentitySet;
-import android.net.NetworkStack;
-import android.net.NetworkStats;
-import android.net.NetworkStatsAccess;
-import android.net.NetworkStatsCollection;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.netstats.IUsageCallback;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Manages observers of {@link NetworkStats}. Allows observers to be notified when
- * data usage has been reported in {@link NetworkStatsService}. An observer can set
- * a threshold of how much data it cares about to be notified.
- */
-class NetworkStatsObservers {
-    private static final String TAG = "NetworkStatsObservers";
-    private static final boolean LOGV = false;
-
-    private static final int MSG_REGISTER = 1;
-    private static final int MSG_UNREGISTER = 2;
-    private static final int MSG_UPDATE_STATS = 3;
-
-    // All access to this map must be done from the handler thread.
-    // indexed by DataUsageRequest#requestId
-    private final SparseArray<RequestInfo> mDataUsageRequests = new SparseArray<>();
-
-    // Sequence number of DataUsageRequests
-    private final AtomicInteger mNextDataUsageRequestId = new AtomicInteger();
-
-    // Lazily instantiated when an observer is registered.
-    private volatile Handler mHandler;
-
-    /**
-     * Creates a wrapper that contains the caller context and a normalized request.
-     * The request should be returned to the caller app, and the wrapper should be sent to this
-     * object through #addObserver by the service handler.
-     *
-     * <p>It will register the observer asynchronously, so it is safe to call from any thread.
-     *
-     * @return the normalized request wrapped within {@link RequestInfo}.
-     */
-    public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
-            IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
-        DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
-        RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
-                accessLevel);
-
-        if (LOGV) Log.v(TAG, "Registering observer for " + request);
-        getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo));
-        return request;
-    }
-
-    /**
-     * Unregister a data usage observer.
-     *
-     * <p>It will unregister the observer asynchronously, so it is safe to call from any thread.
-     */
-    public void unregister(DataUsageRequest request, int callingUid) {
-        getHandler().sendMessage(mHandler.obtainMessage(MSG_UNREGISTER, callingUid, 0 /* ignore */,
-                request));
-    }
-
-    /**
-     * Updates data usage statistics of registered observers and notifies if limits are reached.
-     *
-     * <p>It will update stats asynchronously, so it is safe to call from any thread.
-     */
-    public void updateStats(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
-                ArrayMap<String, NetworkIdentitySet> activeIfaces,
-                ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
-                long currentTime) {
-        StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces,
-                activeUidIfaces, currentTime);
-        getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext));
-    }
-
-    private Handler getHandler() {
-        if (mHandler == null) {
-            synchronized (this) {
-                if (mHandler == null) {
-                    if (LOGV) Log.v(TAG, "Creating handler");
-                    mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback);
-                }
-            }
-        }
-        return mHandler;
-    }
-
-    @VisibleForTesting
-    protected Looper getHandlerLooperLocked() {
-        HandlerThread handlerThread = new HandlerThread(TAG);
-        handlerThread.start();
-        return handlerThread.getLooper();
-    }
-
-    private Handler.Callback mHandlerCallback = new Handler.Callback() {
-        @Override
-        public boolean handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_REGISTER: {
-                    handleRegister((RequestInfo) msg.obj);
-                    return true;
-                }
-                case MSG_UNREGISTER: {
-                    handleUnregister((DataUsageRequest) msg.obj, msg.arg1 /* callingUid */);
-                    return true;
-                }
-                case MSG_UPDATE_STATS: {
-                    handleUpdateStats((StatsContext) msg.obj);
-                    return true;
-                }
-                default: {
-                    return false;
-                }
-            }
-        }
-    };
-
-    /**
-     * Adds a {@link RequestInfo} as an observer.
-     * Should only be called from the handler thread otherwise there will be a race condition
-     * on mDataUsageRequests.
-     */
-    private void handleRegister(RequestInfo requestInfo) {
-        mDataUsageRequests.put(requestInfo.mRequest.requestId, requestInfo);
-    }
-
-    /**
-     * Removes a {@link DataUsageRequest} if the calling uid is authorized.
-     * Should only be called from the handler thread otherwise there will be a race condition
-     * on mDataUsageRequests.
-     */
-    private void handleUnregister(DataUsageRequest request, int callingUid) {
-        RequestInfo requestInfo;
-        requestInfo = mDataUsageRequests.get(request.requestId);
-        if (requestInfo == null) {
-            if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request);
-            return;
-        }
-        if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) {
-            Log.w(TAG, "Caller uid " + callingUid + " is not owner of " + request);
-            return;
-        }
-
-        if (LOGV) Log.v(TAG, "Unregistering " + request);
-        mDataUsageRequests.remove(request.requestId);
-        requestInfo.unlinkDeathRecipient();
-        requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED);
-    }
-
-    private void handleUpdateStats(StatsContext statsContext) {
-        if (mDataUsageRequests.size() == 0) {
-            return;
-        }
-
-        for (int i = 0; i < mDataUsageRequests.size(); i++) {
-            RequestInfo requestInfo = mDataUsageRequests.valueAt(i);
-            requestInfo.updateStats(statsContext);
-        }
-    }
-
-    private DataUsageRequest buildRequest(Context context, DataUsageRequest request,
-                int callingUid) {
-        // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to
-        // avoid too many callbacks.
-        final long thresholdInBytes = (context.checkPermission(
-                NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid)
-                == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes
-                : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
-        if (thresholdInBytes > request.thresholdInBytes) {
-            Log.w(TAG, "Threshold was too low for " + request
-                    + ". Overriding to a safer default of " + thresholdInBytes + " bytes");
-        }
-        return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(),
-                request.template, thresholdInBytes);
-    }
-
-    private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback,
-            int callingUid, @NetworkStatsAccess.Level int accessLevel) {
-        if (accessLevel <= NetworkStatsAccess.Level.USER) {
-            return new UserUsageRequestInfo(this, request, callback, callingUid,
-                    accessLevel);
-        } else {
-            // Safety check in case a new access level is added and we forgot to update this
-            if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
-                throw new IllegalArgumentException(
-                        "accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
-            }
-            return new NetworkUsageRequestInfo(this, request, callback, callingUid,
-                    accessLevel);
-        }
-    }
-
-    /**
-     * Tracks information relevant to a data usage observer.
-     * It will notice when the calling process dies so we can self-expire.
-     */
-    private abstract static class RequestInfo implements IBinder.DeathRecipient {
-        private final NetworkStatsObservers mStatsObserver;
-        protected final DataUsageRequest mRequest;
-        private final IUsageCallback mCallback;
-        protected final int mCallingUid;
-        protected final @NetworkStatsAccess.Level int mAccessLevel;
-        protected NetworkStatsRecorder mRecorder;
-        protected NetworkStatsCollection mCollection;
-
-        RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
-            mStatsObserver = statsObserver;
-            mRequest = request;
-            mCallback = callback;
-            mCallingUid = callingUid;
-            mAccessLevel = accessLevel;
-
-            try {
-                mCallback.asBinder().linkToDeath(this, 0);
-            } catch (RemoteException e) {
-                binderDied();
-            }
-        }
-
-        @Override
-        public void binderDied() {
-            if (LOGV) {
-                Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")");
-            }
-            mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
-            callCallback(NetworkStatsManager.CALLBACK_RELEASED);
-        }
-
-        @Override
-        public String toString() {
-            return "RequestInfo from uid:" + mCallingUid
-                    + " for " + mRequest + " accessLevel:" + mAccessLevel;
-        }
-
-        private void unlinkDeathRecipient() {
-            mCallback.asBinder().unlinkToDeath(this, 0);
-        }
-
-        /**
-         * Update stats given the samples and interface to identity mappings.
-         */
-        private void updateStats(StatsContext statsContext) {
-            if (mRecorder == null) {
-                // First run; establish baseline stats
-                resetRecorder();
-                recordSample(statsContext);
-                return;
-            }
-            recordSample(statsContext);
-
-            if (checkStats()) {
-                resetRecorder();
-                callCallback(NetworkStatsManager.CALLBACK_LIMIT_REACHED);
-            }
-        }
-
-        private void callCallback(int callbackType) {
-            try {
-                if (LOGV) {
-                    Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
-                            + " for " + mRequest);
-                }
-                switch (callbackType) {
-                    case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
-                        mCallback.onThresholdReached(mRequest);
-                        break;
-                    case NetworkStatsManager.CALLBACK_RELEASED:
-                        mCallback.onCallbackReleased(mRequest);
-                        break;
-                }
-            } catch (RemoteException e) {
-                // May occur naturally in the race of binder death.
-                Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
-            }
-        }
-
-        private void resetRecorder() {
-            mRecorder = new NetworkStatsRecorder();
-            mCollection = mRecorder.getSinceBoot();
-        }
-
-        protected abstract boolean checkStats();
-
-        protected abstract void recordSample(StatsContext statsContext);
-
-        private String callbackTypeToName(int callbackType) {
-            switch (callbackType) {
-                case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
-                    return "LIMIT_REACHED";
-                case NetworkStatsManager.CALLBACK_RELEASED:
-                    return "RELEASED";
-                default:
-                    return "UNKNOWN";
-            }
-        }
-    }
-
-    private static class NetworkUsageRequestInfo extends RequestInfo {
-        NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, callback, callingUid, accessLevel);
-        }
-
-        @Override
-        protected boolean checkStats() {
-            long bytesSoFar = getTotalBytesForNetwork(mRequest.template);
-            if (LOGV) {
-                Log.v(TAG, bytesSoFar + " bytes so far since notification for "
-                        + mRequest.template);
-            }
-            if (bytesSoFar > mRequest.thresholdInBytes) {
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        protected void recordSample(StatsContext statsContext) {
-            // Recorder does not need to be locked in this context since only the handler
-            // thread will update it. We pass a null VPN array because usage is aggregated by uid
-            // for this snapshot, so VPN traffic can't be reattributed to responsible apps.
-            mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces,
-                    statsContext.mCurrentTime);
-        }
-
-        /**
-         * Reads stats matching the given template. {@link NetworkStatsCollection} will aggregate
-         * over all buckets, which in this case should be only one since we built it big enough
-         * that it will outlive the caller. If it doesn't, then there will be multiple buckets.
-         */
-        private long getTotalBytesForNetwork(NetworkTemplate template) {
-            NetworkStats stats = mCollection.getSummary(template,
-                    Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
-                    mAccessLevel, mCallingUid);
-            return stats.getTotalBytes();
-        }
-    }
-
-    private static class UserUsageRequestInfo extends RequestInfo {
-        UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
-                    IUsageCallback callback, int callingUid,
-                    @NetworkStatsAccess.Level int accessLevel) {
-            super(statsObserver, request, callback, callingUid, accessLevel);
-        }
-
-        @Override
-        protected boolean checkStats() {
-            int[] uidsToMonitor = mCollection.getRelevantUids(mAccessLevel, mCallingUid);
-
-            for (int i = 0; i < uidsToMonitor.length; i++) {
-                long bytesSoFar = getTotalBytesForNetworkUid(mRequest.template, uidsToMonitor[i]);
-                if (bytesSoFar > mRequest.thresholdInBytes) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected void recordSample(StatsContext statsContext) {
-            // Recorder does not need to be locked in this context since only the handler
-            // thread will update it. We pass the VPN info so VPN traffic is reattributed to
-            // responsible apps.
-            mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces,
-                    statsContext.mCurrentTime);
-        }
-
-        /**
-         * Reads all stats matching the given template and uid. Ther history will likely only
-         * contain one bucket per ident since we build it big enough that it will outlive the
-         * caller lifetime.
-         */
-        private long getTotalBytesForNetworkUid(NetworkTemplate template, int uid) {
-            try {
-                NetworkStatsHistory history = mCollection.getHistory(template, null, uid,
-                        NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
-                        NetworkStatsHistory.FIELD_ALL,
-                        Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */,
-                        mAccessLevel, mCallingUid);
-                return history.getTotalBytes();
-            } catch (SecurityException e) {
-                if (LOGV) {
-                    Log.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid "
-                            + uid);
-                }
-                return 0;
-            }
-        }
-    }
-
-    private static class StatsContext {
-        NetworkStats mXtSnapshot;
-        NetworkStats mUidSnapshot;
-        ArrayMap<String, NetworkIdentitySet> mActiveIfaces;
-        ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces;
-        long mCurrentTime;
-
-        StatsContext(NetworkStats xtSnapshot, NetworkStats uidSnapshot,
-                ArrayMap<String, NetworkIdentitySet> activeIfaces,
-                ArrayMap<String, NetworkIdentitySet> activeUidIfaces,
-                long currentTime) {
-            mXtSnapshot = xtSnapshot;
-            mUidSnapshot = uidSnapshot;
-            mActiveIfaces = activeIfaces;
-            mActiveUidIfaces = activeUidIfaces;
-            mCurrentTime = currentTime;
-        }
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
deleted file mode 100644
index f62765d..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.TrafficStats.KB_IN_BYTES;
-import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.text.format.DateUtils.YEAR_IN_MILLIS;
-
-import android.net.NetworkIdentitySet;
-import android.net.NetworkStats;
-import android.net.NetworkStats.NonMonotonicObserver;
-import android.net.NetworkStatsAccess;
-import android.net.NetworkStatsCollection;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.TrafficStats;
-import android.os.Binder;
-import android.os.DropBoxManager;
-import android.service.NetworkStatsRecorderProto;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.util.FileRotator;
-import com.android.net.module.util.NetworkStatsUtils;
-
-import libcore.io.IoUtils;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Logic to record deltas between periodic {@link NetworkStats} snapshots into
- * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}.
- * Keeps pending changes in memory until they pass a specific threshold, in
- * bytes. Uses {@link FileRotator} for persistence logic if present.
- * <p>
- * Not inherently thread safe.
- */
-public class NetworkStatsRecorder {
-    private static final String TAG = "NetworkStatsRecorder";
-    private static final boolean LOGD = false;
-    private static final boolean LOGV = false;
-
-    private static final String TAG_NETSTATS_DUMP = "netstats_dump";
-
-    /** Dump before deleting in {@link #recoverFromWtf()}. */
-    private static final boolean DUMP_BEFORE_DELETE = true;
-
-    private final FileRotator mRotator;
-    private final NonMonotonicObserver<String> mObserver;
-    private final DropBoxManager mDropBox;
-    private final String mCookie;
-
-    private final long mBucketDuration;
-    private final boolean mOnlyTags;
-
-    private long mPersistThresholdBytes = 2 * MB_IN_BYTES;
-    private NetworkStats mLastSnapshot;
-
-    private final NetworkStatsCollection mPending;
-    private final NetworkStatsCollection mSinceBoot;
-
-    private final CombiningRewriter mPendingRewriter;
-
-    private WeakReference<NetworkStatsCollection> mComplete;
-
-    /**
-     * Non-persisted recorder, with only one bucket. Used by {@link NetworkStatsObservers}.
-     */
-    public NetworkStatsRecorder() {
-        mRotator = null;
-        mObserver = null;
-        mDropBox = null;
-        mCookie = null;
-
-        // set the bucket big enough to have all data in one bucket, but allow some
-        // slack to avoid overflow
-        mBucketDuration = YEAR_IN_MILLIS;
-        mOnlyTags = false;
-
-        mPending = null;
-        mSinceBoot = new NetworkStatsCollection(mBucketDuration);
-
-        mPendingRewriter = null;
-    }
-
-    /**
-     * Persisted recorder.
-     */
-    public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
-            DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
-        mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
-        mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
-        mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
-        mCookie = cookie;
-
-        mBucketDuration = bucketDuration;
-        mOnlyTags = onlyTags;
-
-        mPending = new NetworkStatsCollection(bucketDuration);
-        mSinceBoot = new NetworkStatsCollection(bucketDuration);
-
-        mPendingRewriter = new CombiningRewriter(mPending);
-    }
-
-    public void setPersistThreshold(long thresholdBytes) {
-        if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes);
-        mPersistThresholdBytes = NetworkStatsUtils.constrain(
-                thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES);
-    }
-
-    public void resetLocked() {
-        mLastSnapshot = null;
-        if (mPending != null) {
-            mPending.reset();
-        }
-        if (mSinceBoot != null) {
-            mSinceBoot.reset();
-        }
-        if (mComplete != null) {
-            mComplete.clear();
-        }
-    }
-
-    public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) {
-        return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE,
-                NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotal(null);
-    }
-
-    public NetworkStatsCollection getSinceBoot() {
-        return mSinceBoot;
-    }
-
-    /**
-     * Load complete history represented by {@link FileRotator}. Caches
-     * internally as a {@link WeakReference}, and updated with future
-     * {@link #recordSnapshotLocked(NetworkStats, Map, long)} snapshots as long
-     * as reference is valid.
-     */
-    public NetworkStatsCollection getOrLoadCompleteLocked() {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-        NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
-        if (res == null) {
-            res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
-            mComplete = new WeakReference<NetworkStatsCollection>(res);
-        }
-        return res;
-    }
-
-    public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-        NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
-        if (res == null) {
-            res = loadLocked(start, end);
-        }
-        return res;
-    }
-
-    private NetworkStatsCollection loadLocked(long start, long end) {
-        if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie);
-        final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration);
-        try {
-            mRotator.readMatching(res, start, end);
-            res.recordCollection(mPending);
-        } catch (IOException e) {
-            Log.wtf(TAG, "problem completely reading network stats", e);
-            recoverFromWtf();
-        } catch (OutOfMemoryError e) {
-            Log.wtf(TAG, "problem completely reading network stats", e);
-            recoverFromWtf();
-        }
-        return res;
-    }
-
-    /**
-     * Record any delta that occurred since last {@link NetworkStats} snapshot, using the given
-     * {@link Map} to identify network interfaces. First snapshot is considered bootstrap, and is
-     * not counted as delta.
-     */
-    public void recordSnapshotLocked(NetworkStats snapshot,
-            Map<String, NetworkIdentitySet> ifaceIdent, long currentTimeMillis) {
-        final HashSet<String> unknownIfaces = new HashSet<>();
-
-        // skip recording when snapshot missing
-        if (snapshot == null) return;
-
-        // assume first snapshot is bootstrap and don't record
-        if (mLastSnapshot == null) {
-            mLastSnapshot = snapshot;
-            return;
-        }
-
-        final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
-
-        final NetworkStats delta = NetworkStats.subtract(
-                snapshot, mLastSnapshot, mObserver, mCookie);
-        final long end = currentTimeMillis;
-        final long start = end - delta.getElapsedRealtime();
-
-        NetworkStats.Entry entry = null;
-        for (int i = 0; i < delta.size(); i++) {
-            entry = delta.getValues(i, entry);
-
-            // As a last-ditch check, report any negative values and
-            // clamp them so recording below doesn't croak.
-            if (entry.isNegative()) {
-                if (mObserver != null) {
-                    mObserver.foundNonMonotonic(delta, i, mCookie);
-                }
-                entry.rxBytes = Math.max(entry.rxBytes, 0);
-                entry.rxPackets = Math.max(entry.rxPackets, 0);
-                entry.txBytes = Math.max(entry.txBytes, 0);
-                entry.txPackets = Math.max(entry.txPackets, 0);
-                entry.operations = Math.max(entry.operations, 0);
-            }
-
-            final NetworkIdentitySet ident = ifaceIdent.get(entry.iface);
-            if (ident == null) {
-                unknownIfaces.add(entry.iface);
-                continue;
-            }
-
-            // skip when no delta occurred
-            if (entry.isEmpty()) continue;
-
-            // only record tag data when requested
-            if ((entry.tag == TAG_NONE) != mOnlyTags) {
-                if (mPending != null) {
-                    mPending.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
-                }
-
-                // also record against boot stats when present
-                if (mSinceBoot != null) {
-                    mSinceBoot.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
-                }
-
-                // also record against complete dataset when present
-                if (complete != null) {
-                    complete.recordData(ident, entry.uid, entry.set, entry.tag, start, end, entry);
-                }
-            }
-        }
-
-        mLastSnapshot = snapshot;
-
-        if (LOGV && unknownIfaces.size() > 0) {
-            Log.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats");
-        }
-    }
-
-    /**
-     * Consider persisting any pending deltas, if they are beyond
-     * {@link #mPersistThresholdBytes}.
-     */
-    public void maybePersistLocked(long currentTimeMillis) {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-        final long pendingBytes = mPending.getTotalBytes();
-        if (pendingBytes >= mPersistThresholdBytes) {
-            forcePersistLocked(currentTimeMillis);
-        } else {
-            mRotator.maybeRotate(currentTimeMillis);
-        }
-    }
-
-    /**
-     * Force persisting any pending deltas.
-     */
-    public void forcePersistLocked(long currentTimeMillis) {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-        if (mPending.isDirty()) {
-            if (LOGD) Log.d(TAG, "forcePersistLocked() writing for " + mCookie);
-            try {
-                mRotator.rewriteActive(mPendingRewriter, currentTimeMillis);
-                mRotator.maybeRotate(currentTimeMillis);
-                mPending.reset();
-            } catch (IOException e) {
-                Log.wtf(TAG, "problem persisting pending stats", e);
-                recoverFromWtf();
-            } catch (OutOfMemoryError e) {
-                Log.wtf(TAG, "problem persisting pending stats", e);
-                recoverFromWtf();
-            }
-        }
-    }
-
-    /**
-     * Remove the given UID from all {@link FileRotator} history, migrating it
-     * to {@link TrafficStats#UID_REMOVED}.
-     */
-    public void removeUidsLocked(int[] uids) {
-        if (mRotator != null) {
-            try {
-                // Rewrite all persisted data to migrate UID stats
-                mRotator.rewriteAll(new RemoveUidRewriter(mBucketDuration, uids));
-            } catch (IOException e) {
-                Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
-                recoverFromWtf();
-            } catch (OutOfMemoryError e) {
-                Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
-                recoverFromWtf();
-            }
-        }
-
-        // Remove any pending stats
-        if (mPending != null) {
-            mPending.removeUids(uids);
-        }
-        if (mSinceBoot != null) {
-            mSinceBoot.removeUids(uids);
-        }
-
-        // Clear UID from current stats snapshot
-        if (mLastSnapshot != null) {
-            mLastSnapshot.removeUids(uids);
-        }
-
-        final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
-        if (complete != null) {
-            complete.removeUids(uids);
-        }
-    }
-
-    /**
-     * Rewriter that will combine current {@link NetworkStatsCollection} values
-     * with anything read from disk, and write combined set to disk. Clears the
-     * original {@link NetworkStatsCollection} when finished writing.
-     */
-    private static class CombiningRewriter implements FileRotator.Rewriter {
-        private final NetworkStatsCollection mCollection;
-
-        public CombiningRewriter(NetworkStatsCollection collection) {
-            mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
-        }
-
-        @Override
-        public void reset() {
-            // ignored
-        }
-
-        @Override
-        public void read(InputStream in) throws IOException {
-            mCollection.read(in);
-        }
-
-        @Override
-        public boolean shouldWrite() {
-            return true;
-        }
-
-        @Override
-        public void write(OutputStream out) throws IOException {
-            mCollection.write(out);
-            mCollection.reset();
-        }
-    }
-
-    /**
-     * Rewriter that will remove any {@link NetworkStatsHistory} attributed to
-     * the requested UID, only writing data back when modified.
-     */
-    public static class RemoveUidRewriter implements FileRotator.Rewriter {
-        private final NetworkStatsCollection mTemp;
-        private final int[] mUids;
-
-        public RemoveUidRewriter(long bucketDuration, int[] uids) {
-            mTemp = new NetworkStatsCollection(bucketDuration);
-            mUids = uids;
-        }
-
-        @Override
-        public void reset() {
-            mTemp.reset();
-        }
-
-        @Override
-        public void read(InputStream in) throws IOException {
-            mTemp.read(in);
-            mTemp.clearDirty();
-            mTemp.removeUids(mUids);
-        }
-
-        @Override
-        public boolean shouldWrite() {
-            return mTemp.isDirty();
-        }
-
-        @Override
-        public void write(OutputStream out) throws IOException {
-            mTemp.write(out);
-        }
-    }
-
-    public void importLegacyNetworkLocked(File file) throws IOException {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-
-        // legacy file still exists; start empty to avoid double importing
-        mRotator.deleteAll();
-
-        final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
-        collection.readLegacyNetwork(file);
-
-        final long startMillis = collection.getStartMillis();
-        final long endMillis = collection.getEndMillis();
-
-        if (!collection.isEmpty()) {
-            // process legacy data, creating active file at starting time, then
-            // using end time to possibly trigger rotation.
-            mRotator.rewriteActive(new CombiningRewriter(collection), startMillis);
-            mRotator.maybeRotate(endMillis);
-        }
-    }
-
-    public void importLegacyUidLocked(File file) throws IOException {
-        Objects.requireNonNull(mRotator, "missing FileRotator");
-
-        // legacy file still exists; start empty to avoid double importing
-        mRotator.deleteAll();
-
-        final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
-        collection.readLegacyUid(file, mOnlyTags);
-
-        final long startMillis = collection.getStartMillis();
-        final long endMillis = collection.getEndMillis();
-
-        if (!collection.isEmpty()) {
-            // process legacy data, creating active file at starting time, then
-            // using end time to possibly trigger rotation.
-            mRotator.rewriteActive(new CombiningRewriter(collection), startMillis);
-            mRotator.maybeRotate(endMillis);
-        }
-    }
-
-    public void dumpLocked(IndentingPrintWriter pw, boolean fullHistory) {
-        if (mPending != null) {
-            pw.print("Pending bytes: "); pw.println(mPending.getTotalBytes());
-        }
-        if (fullHistory) {
-            pw.println("Complete history:");
-            getOrLoadCompleteLocked().dump(pw);
-        } else {
-            pw.println("History since boot:");
-            mSinceBoot.dump(pw);
-        }
-    }
-
-    public void dumpDebugLocked(ProtoOutputStream proto, long tag) {
-        final long start = proto.start(tag);
-        if (mPending != null) {
-            proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES,
-                    mPending.getTotalBytes());
-        }
-        getOrLoadCompleteLocked().dumpDebug(proto,
-                NetworkStatsRecorderProto.COMPLETE_HISTORY);
-        proto.end(start);
-    }
-
-    public void dumpCheckin(PrintWriter pw, long start, long end) {
-        // Only load and dump stats from the requested window
-        getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end);
-    }
-
-    /**
-     * Recover from {@link FileRotator} failure by dumping state to
-     * {@link DropBoxManager} and deleting contents.
-     */
-    private void recoverFromWtf() {
-        if (DUMP_BEFORE_DELETE) {
-            final ByteArrayOutputStream os = new ByteArrayOutputStream();
-            try {
-                mRotator.dumpAll(os);
-            } catch (IOException e) {
-                // ignore partial contents
-                os.reset();
-            } finally {
-                IoUtils.closeQuietly(os);
-            }
-            mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0);
-        }
-
-        mRotator.deleteAll();
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
deleted file mode 100644
index e3794e4..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ /dev/null
@@ -1,2528 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
-import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
-import static android.Manifest.permission.UPDATE_DEVICE_STATS;
-import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
-import static android.content.Intent.ACTION_SHUTDOWN;
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.ACTION_USER_REMOVED;
-import static android.content.Intent.EXTRA_UID;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.IFACE_VT;
-import static android.net.NetworkStats.INTERFACES_ALL;
-import static android.net.NetworkStats.METERED_ALL;
-import static android.net.NetworkStats.ROAMING_ALL;
-import static android.net.NetworkStats.SET_ALL;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.SET_FOREGROUND;
-import static android.net.NetworkStats.STATS_PER_IFACE;
-import static android.net.NetworkStats.STATS_PER_UID;
-import static android.net.NetworkStats.TAG_ALL;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.FIELD_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
-import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.TrafficStats.KB_IN_BYTES;
-import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.net.TrafficStats.UID_TETHERING;
-import static android.net.TrafficStats.UNSUPPORTED;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
-import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
-import static android.os.Trace.TRACE_TAG_NETWORK;
-import static android.system.OsConstants.ENOENT;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-import static android.text.format.DateUtils.DAY_IN_MILLIS;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-
-import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
-import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.TargetApi;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.usage.NetworkStatsManager;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.net.DataUsageRequest;
-import android.net.INetd;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkIdentity;
-import android.net.NetworkIdentitySet;
-import android.net.NetworkPolicyManager;
-import android.net.NetworkSpecifier;
-import android.net.NetworkStack;
-import android.net.NetworkStateSnapshot;
-import android.net.NetworkStats;
-import android.net.NetworkStats.NonMonotonicObserver;
-import android.net.NetworkStatsAccess;
-import android.net.NetworkStatsCollection;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.net.TelephonyNetworkSpecifier;
-import android.net.TetherStatsParcel;
-import android.net.TetheringManager;
-import android.net.TrafficStats;
-import android.net.UnderlyingNetworkInfo;
-import android.net.Uri;
-import android.net.netstats.IUsageCallback;
-import android.net.netstats.provider.INetworkStatsProvider;
-import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Binder;
-import android.os.Build;
-import android.os.DropBoxManager;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Settings.Global;
-import android.service.NetworkInterfaceProto;
-import android.service.NetworkStatsServiceDumpProto;
-import android.system.ErrnoException;
-import android.telephony.PhoneStateListener;
-import android.telephony.SubscriptionPlan;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.EventLog;
-import android.util.IndentingPrintWriter;
-import android.util.Log;
-import android.util.SparseIntArray;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FileRotator;
-import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
-import com.android.net.module.util.BestClock;
-import com.android.net.module.util.BinderUtils;
-import com.android.net.module.util.BpfMap;
-import com.android.net.module.util.CollectionUtils;
-import com.android.net.module.util.IBpfMap;
-import com.android.net.module.util.LocationPermissionChecker;
-import com.android.net.module.util.NetworkStatsUtils;
-import com.android.net.module.util.PermissionUtils;
-import com.android.net.module.util.Struct.U32;
-import com.android.net.module.util.Struct.U8;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.time.Clock;
-import java.time.ZoneOffset;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Collect and persist detailed network statistics, and provide this data to
- * other system services.
- */
-@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public class NetworkStatsService extends INetworkStatsService.Stub {
-    static {
-        System.loadLibrary("service-connectivity");
-    }
-
-    static final String TAG = "NetworkStats";
-    static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
-    static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
-
-    // Perform polling and persist all (FLAG_PERSIST_ALL).
-    private static final int MSG_PERFORM_POLL = 1;
-    // Perform polling, persist network, and register the global alert again.
-    private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
-    private static final int MSG_NOTIFY_NETWORK_STATUS = 3;
-    // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent
-    // deadlock.
-    private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4;
-
-    /** Flags to control detail level of poll event. */
-    private static final int FLAG_PERSIST_NETWORK = 0x1;
-    private static final int FLAG_PERSIST_UID = 0x2;
-    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
-    private static final int FLAG_PERSIST_FORCE = 0x100;
-
-    /**
-     * When global alert quota is high, wait for this delay before processing each polling,
-     * and do not schedule further polls once there is already one queued.
-     * This avoids firing the global alert too often on devices with high transfer speeds and
-     * high quota.
-     */
-    private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000;
-
-    private static final String TAG_NETSTATS_ERROR = "netstats_error";
-
-    /**
-     * EventLog tags used when logging into the event log. Note the values must be sync with
-     * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct
-     * name translation.
-      */
-    private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100;
-    private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101;
-
-    // TODO: Replace the hardcoded string and move it into ConnectivitySettingsManager.
-    private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED =
-            "netstats_combine_subtype_enabled";
-
-    // This is current path but may be changed soon.
-    private static final String UID_COUNTERSET_MAP_PATH =
-            "/sys/fs/bpf/map_netd_uid_counterset_map";
-    private static final String COOKIE_TAG_MAP_PATH =
-            "/sys/fs/bpf/map_netd_cookie_tag_map";
-    private static final String APP_UID_STATS_MAP_PATH =
-            "/sys/fs/bpf/map_netd_app_uid_stats_map";
-    private static final String STATS_MAP_A_PATH =
-            "/sys/fs/bpf/map_netd_stats_map_A";
-    private static final String STATS_MAP_B_PATH =
-            "/sys/fs/bpf/map_netd_stats_map_B";
-
-    private final Context mContext;
-    private final NetworkStatsFactory mStatsFactory;
-    private final AlarmManager mAlarmManager;
-    private final Clock mClock;
-    private final NetworkStatsSettings mSettings;
-    private final NetworkStatsObservers mStatsObservers;
-
-    private final File mSystemDir;
-    private final File mBaseDir;
-
-    private final PowerManager.WakeLock mWakeLock;
-
-    private final ContentObserver mContentObserver;
-    private final ContentResolver mContentResolver;
-
-    protected INetd mNetd;
-    private final AlertObserver mAlertObserver = new AlertObserver();
-
-    @VisibleForTesting
-    public static final String ACTION_NETWORK_STATS_POLL =
-            "com.android.server.action.NETWORK_STATS_POLL";
-    public static final String ACTION_NETWORK_STATS_UPDATED =
-            "com.android.server.action.NETWORK_STATS_UPDATED";
-
-    private PendingIntent mPollIntent;
-
-    /**
-     * Settings that can be changed externally.
-     */
-    public interface NetworkStatsSettings {
-        long getPollInterval();
-        long getPollDelay();
-        boolean getSampleEnabled();
-        boolean getAugmentEnabled();
-        /**
-         * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}.
-         * When disabled, mobile data is broken down by a granular ratType representative of the
-         * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}.
-         * Enabling this decreases the level of detail but saves performance, disk space and
-         * amount of data logged.
-         */
-        boolean getCombineSubtypeEnabled();
-
-        class Config {
-            public final long bucketDuration;
-            public final long rotateAgeMillis;
-            public final long deleteAgeMillis;
-
-            public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
-                this.bucketDuration = bucketDuration;
-                this.rotateAgeMillis = rotateAgeMillis;
-                this.deleteAgeMillis = deleteAgeMillis;
-            }
-        }
-
-        Config getDevConfig();
-        Config getXtConfig();
-        Config getUidConfig();
-        Config getUidTagConfig();
-
-        long getGlobalAlertBytes(long def);
-        long getDevPersistBytes(long def);
-        long getXtPersistBytes(long def);
-        long getUidPersistBytes(long def);
-        long getUidTagPersistBytes(long def);
-    }
-
-    private final Object mStatsLock = new Object();
-
-    /** Set of currently active ifaces. */
-    @GuardedBy("mStatsLock")
-    private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
-
-    /** Set of currently active ifaces for UID stats. */
-    @GuardedBy("mStatsLock")
-    private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
-
-    /** Current default active iface. */
-    @GuardedBy("mStatsLock")
-    private String mActiveIface;
-
-    /** Set of any ifaces associated with mobile networks since boot. */
-    private volatile String[] mMobileIfaces = new String[0];
-
-    /** Set of any ifaces associated with wifi networks since boot. */
-    private volatile String[] mWifiIfaces = new String[0];
-
-    /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
-    @GuardedBy("mStatsLock")
-    private Network[] mDefaultNetworks = new Network[0];
-
-    /** Last states of all networks sent from ConnectivityService. */
-    @GuardedBy("mStatsLock")
-    @Nullable
-    private NetworkStateSnapshot[] mLastNetworkStateSnapshots = null;
-
-    private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
-            new DropBoxNonMonotonicObserver();
-
-    private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100;
-    private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
-            new CopyOnWriteArrayList<>();
-    /** Semaphore used to wait for stats provider to respond to request stats update. */
-    private final Semaphore mStatsProviderSem = new Semaphore(0, true);
-
-    @GuardedBy("mStatsLock")
-    private NetworkStatsRecorder mDevRecorder;
-    @GuardedBy("mStatsLock")
-    private NetworkStatsRecorder mXtRecorder;
-    @GuardedBy("mStatsLock")
-    private NetworkStatsRecorder mUidRecorder;
-    @GuardedBy("mStatsLock")
-    private NetworkStatsRecorder mUidTagRecorder;
-
-    /** Cached {@link #mXtRecorder} stats. */
-    @GuardedBy("mStatsLock")
-    private NetworkStatsCollection mXtStatsCached;
-
-    /**
-     * Current counter sets for each UID.
-     * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap
-     * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep
-     * mActiveUidCounterSet to avoid accessing kernel too frequently.
-     */
-    private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
-    private final IBpfMap<U32, U8> mUidCounterSetMap;
-    private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
-    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapA;
-    private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapB;
-    private final IBpfMap<UidStatsMapKey, StatsMapValue> mAppUidStatsMap;
-
-    /** Data layer operation counters for splicing into other structures. */
-    private NetworkStats mUidOperations = new NetworkStats(0L, 10);
-
-    @NonNull
-    private final Handler mHandler;
-
-    private volatile boolean mSystemReady;
-    private long mPersistThreshold = 2 * MB_IN_BYTES;
-    private long mGlobalAlertBytes;
-
-    private static final long POLL_RATE_LIMIT_MS = 15_000;
-
-    private long mLastStatsSessionPoll;
-
-    /** Map from UID to number of opened sessions */
-    @GuardedBy("mOpenSessionCallsPerUid")
-    private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
-
-    private final static int DUMP_STATS_SESSION_COUNT = 20;
-
-    @NonNull
-    private final Dependencies mDeps;
-
-    @NonNull
-    private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
-
-    @NonNull
-    private final LocationPermissionChecker mLocationPermissionChecker;
-
-    @NonNull
-    private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
-
-    private static @NonNull File getDefaultSystemDir() {
-        return new File(Environment.getDataDirectory(), "system");
-    }
-
-    private static @NonNull File getDefaultBaseDir() {
-        File baseDir = new File(getDefaultSystemDir(), "netstats");
-        baseDir.mkdirs();
-        return baseDir;
-    }
-
-    private static @NonNull Clock getDefaultClock() {
-        return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
-                Clock.systemUTC());
-    }
-
-    private final class NetworkStatsHandler extends Handler {
-        NetworkStatsHandler(@NonNull Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_PERFORM_POLL: {
-                    performPoll(FLAG_PERSIST_ALL);
-                    break;
-                }
-                case MSG_NOTIFY_NETWORK_STATUS: {
-                    // If no cached states, ignore.
-                    if (mLastNetworkStateSnapshots == null) break;
-                    // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing.
-                    handleNotifyNetworkStatus(
-                            mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
-                    break;
-                }
-                case MSG_PERFORM_POLL_REGISTER_ALERT: {
-                    performPoll(FLAG_PERSIST_NETWORK);
-                    registerGlobalAlert();
-                    break;
-                }
-                case MSG_BROADCAST_NETWORK_STATS_UPDATED: {
-                    final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
-                    updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                    mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
-                            READ_NETWORK_USAGE_HISTORY);
-                    break;
-                }
-            }
-        }
-    }
-
-    /** Creates a new NetworkStatsService */
-    public static NetworkStatsService create(Context context) {
-        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        PowerManager.WakeLock wakeLock =
-                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
-        final INetd netd = INetd.Stub.asInterface(
-                (IBinder) context.getSystemService(Context.NETD_SERVICE));
-        final NetworkStatsService service = new NetworkStatsService(context,
-                INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
-                alarmManager, wakeLock, getDefaultClock(),
-                new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context),
-                new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
-                new Dependencies());
-
-        return service;
-    }
-
-    // This must not be called outside of tests, even within the same package, as this constructor
-    // does not register the local service. Use the create() helper above.
-    @VisibleForTesting
-    NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
-            PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
-            NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
-            File baseDir, @NonNull Dependencies deps) {
-        mContext = Objects.requireNonNull(context, "missing Context");
-        mNetd = Objects.requireNonNull(netd, "missing Netd");
-        mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
-        mClock = Objects.requireNonNull(clock, "missing Clock");
-        mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
-        mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
-        mStatsFactory = Objects.requireNonNull(factory, "missing factory");
-        mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
-        mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
-        mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
-        mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
-        final HandlerThread handlerThread = mDeps.makeHandlerThread();
-        handlerThread.start();
-        mHandler = new NetworkStatsHandler(handlerThread.getLooper());
-        mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
-                (command) -> mHandler.post(command) , this);
-        mContentResolver = mContext.getContentResolver();
-        mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
-                mNetworkStatsSubscriptionsMonitor);
-        mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
-        mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
-        mInterfaceMapUpdater.start();
-        mUidCounterSetMap = mDeps.getUidCounterSetMap();
-        mCookieTagMap = mDeps.getCookieTagMap();
-        mStatsMapA = mDeps.getStatsMapA();
-        mStatsMapB = mDeps.getStatsMapB();
-        mAppUidStatsMap = mDeps.getAppUidStatsMap();
-    }
-
-    /**
-     * Dependencies of NetworkStatsService, for injection in tests.
-     */
-    // TODO: Move more stuff into dependencies object.
-    @VisibleForTesting
-    public static class Dependencies {
-        /**
-         * Create a HandlerThread to use in NetworkStatsService.
-         */
-        @NonNull
-        public HandlerThread makeHandlerThread() {
-            return new HandlerThread(TAG);
-        }
-
-        /**
-         * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change
-         * event in NetworkStatsService.
-         */
-        @NonNull
-        public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
-                @NonNull Executor executor, @NonNull NetworkStatsService service) {
-            // TODO: Update RatType passively in NSS, instead of querying into the monitor
-            //  when notifyNetworkStatus.
-            return new NetworkStatsSubscriptionsMonitor(context, executor,
-                    (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
-        }
-
-        /**
-         * Create a ContentObserver instance which is used to observe settings changes,
-         * and dispatch onChange events on handler thread.
-         */
-        public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler,
-                @NonNull NetworkStatsSettings settings,
-                @NonNull NetworkStatsSubscriptionsMonitor monitor) {
-            return new ContentObserver(handler) {
-                @Override
-                public void onChange(boolean selfChange, @NonNull Uri uri) {
-                    if (!settings.getCombineSubtypeEnabled()) {
-                        monitor.start();
-                    } else {
-                        monitor.stop();
-                    }
-                }
-            };
-        }
-
-        /**
-         * @see LocationPermissionChecker
-         */
-        public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
-            return new LocationPermissionChecker(context);
-        }
-
-        /** Create BpfInterfaceMapUpdater to update bpf interface map. */
-        @NonNull
-        public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater(
-                @NonNull Context ctx, @NonNull Handler handler) {
-            return new BpfInterfaceMapUpdater(ctx, handler);
-        }
-
-        /** Get counter sets map for each UID. */
-        public IBpfMap<U32, U8> getUidCounterSetMap() {
-            try {
-                return new BpfMap<U32, U8>(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR,
-                        U32.class, U8.class);
-            } catch (ErrnoException e) {
-                Log.wtf(TAG, "Cannot open uid counter set map: " + e);
-                return null;
-            }
-        }
-
-        /** Gets the cookie tag map */
-        public IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
-            try {
-                return new BpfMap<CookieTagMapKey, CookieTagMapValue>(COOKIE_TAG_MAP_PATH,
-                        BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class);
-            } catch (ErrnoException e) {
-                Log.wtf(TAG, "Cannot open cookie tag map: " + e);
-                return null;
-            }
-        }
-
-        /** Gets stats map A */
-        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapA() {
-            try {
-                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_A_PATH,
-                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
-            } catch (ErrnoException e) {
-                Log.wtf(TAG, "Cannot open stats map A: " + e);
-                return null;
-            }
-        }
-
-        /** Gets stats map B */
-        public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapB() {
-            try {
-                return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_B_PATH,
-                        BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
-            } catch (ErrnoException e) {
-                Log.wtf(TAG, "Cannot open stats map B: " + e);
-                return null;
-            }
-        }
-
-        /** Gets the uid stats map */
-        public IBpfMap<UidStatsMapKey, StatsMapValue> getAppUidStatsMap() {
-            try {
-                return new BpfMap<UidStatsMapKey, StatsMapValue>(APP_UID_STATS_MAP_PATH,
-                        BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class);
-            } catch (ErrnoException e) {
-                Log.wtf(TAG, "Cannot open app uid stats map: " + e);
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Observer that watches for {@link INetdUnsolicitedEventListener} alerts.
-     */
-    @VisibleForTesting
-    public class AlertObserver extends BaseNetdUnsolicitedEventListener {
-        @Override
-        public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) {
-            PermissionUtils.enforceNetworkStackPermission(mContext);
-
-            if (LIMIT_GLOBAL_ALERT.equals(alertName)) {
-                // kick off background poll to collect network stats unless there is already
-                // such a call pending; UID stats are handled during normal polling interval.
-                if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
-                    mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
-                            mSettings.getPollDelay());
-                }
-            }
-        }
-    }
-
-    public void systemReady() {
-        synchronized (mStatsLock) {
-            mSystemReady = true;
-
-            // create data recorders along with historical rotators
-            mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
-            mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
-            mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
-            mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
-
-            updatePersistThresholdsLocked();
-
-            // upgrade any legacy stats, migrating them to rotated files
-            maybeUpgradeLegacyStatsLocked();
-
-            // read historical network stats from disk, since policy service
-            // might need them right away.
-            mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
-
-            // bootstrap initial stats to prevent double-counting later
-            bootstrapStatsLocked();
-        }
-
-        // watch for tethering changes
-        final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
-        tetheringManager.registerTetheringEventCallback(
-                (command) -> mHandler.post(command), mTetherListener);
-
-        // listen for periodic polling events
-        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
-        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
-
-        // listen for uid removal to clean stats
-        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
-        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
-
-        // listen for user changes to clean stats
-        final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
-        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
-
-        // persist stats during clean shutdown
-        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
-        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
-
-        try {
-            mNetd.registerUnsolicitedEventListener(mAlertObserver);
-        } catch (RemoteException | ServiceSpecificException e) {
-            Log.wtf(TAG, "Error registering event listener :", e);
-        }
-
-        //  schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
-        final PendingIntent pollIntent =
-                PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL),
-                        PendingIntent.FLAG_IMMUTABLE);
-
-        final long currentRealtime = SystemClock.elapsedRealtime();
-        mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
-                mSettings.getPollInterval(), pollIntent);
-
-        mContentResolver.registerContentObserver(Settings.Global
-                .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED),
-                        false /* notifyForDescendants */, mContentObserver);
-
-        // Post a runnable on handler thread to call onChange(). It's for getting current value of
-        // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
-        mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
-                .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED)));
-
-        registerGlobalAlert();
-    }
-
-    private NetworkStatsRecorder buildRecorder(
-            String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
-        final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
-                Context.DROPBOX_SERVICE);
-        return new NetworkStatsRecorder(new FileRotator(
-                mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
-                mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
-    }
-
-    @GuardedBy("mStatsLock")
-    private void shutdownLocked() {
-        final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
-        tetheringManager.unregisterTetheringEventCallback(mTetherListener);
-        mContext.unregisterReceiver(mPollReceiver);
-        mContext.unregisterReceiver(mRemovedReceiver);
-        mContext.unregisterReceiver(mUserReceiver);
-        mContext.unregisterReceiver(mShutdownReceiver);
-
-        if (!mSettings.getCombineSubtypeEnabled()) {
-            mNetworkStatsSubscriptionsMonitor.stop();
-        }
-
-        mContentResolver.unregisterContentObserver(mContentObserver);
-
-        final long currentTime = mClock.millis();
-
-        // persist any pending stats
-        mDevRecorder.forcePersistLocked(currentTime);
-        mXtRecorder.forcePersistLocked(currentTime);
-        mUidRecorder.forcePersistLocked(currentTime);
-        mUidTagRecorder.forcePersistLocked(currentTime);
-
-        mSystemReady = false;
-    }
-
-    @GuardedBy("mStatsLock")
-    private void maybeUpgradeLegacyStatsLocked() {
-        File file;
-        try {
-            file = new File(mSystemDir, "netstats.bin");
-            if (file.exists()) {
-                mDevRecorder.importLegacyNetworkLocked(file);
-                file.delete();
-            }
-
-            file = new File(mSystemDir, "netstats_xt.bin");
-            if (file.exists()) {
-                file.delete();
-            }
-
-            file = new File(mSystemDir, "netstats_uid.bin");
-            if (file.exists()) {
-                mUidRecorder.importLegacyUidLocked(file);
-                mUidTagRecorder.importLegacyUidLocked(file);
-                file.delete();
-            }
-        } catch (IOException e) {
-            Log.wtf(TAG, "problem during legacy upgrade", e);
-        } catch (OutOfMemoryError e) {
-            Log.wtf(TAG, "problem during legacy upgrade", e);
-        }
-    }
-
-    /**
-     * Register for a global alert that is delivered through {@link AlertObserver}
-     * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
-     * been transferred.
-     */
-    private void registerGlobalAlert() {
-        try {
-            mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes);
-        } catch (IllegalStateException e) {
-            Log.w(TAG, "problem registering for global alert: " + e);
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
-        }
-        invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes));
-    }
-
-    @Override
-    public INetworkStatsSession openSession() {
-        return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
-    }
-
-    @Override
-    public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) {
-        return openSessionInternal(flags, callingPackage);
-    }
-
-    private boolean isRateLimitedForPoll(int callingUid) {
-        if (callingUid == android.os.Process.SYSTEM_UID) {
-            return false;
-        }
-
-        final long lastCallTime;
-        final long now = SystemClock.elapsedRealtime();
-        synchronized (mOpenSessionCallsPerUid) {
-            int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
-            mOpenSessionCallsPerUid.put(callingUid, calls + 1);
-            lastCallTime = mLastStatsSessionPoll;
-            mLastStatsSessionPoll = now;
-        }
-
-        return now - lastCallTime < POLL_RATE_LIMIT_MS;
-    }
-
-    private int restrictFlagsForCaller(int flags) {
-        // All non-privileged callers are not allowed to turn off POLL_ON_OPEN.
-        final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext,
-                NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
-                android.Manifest.permission.NETWORK_STACK);
-        if (!isPrivileged) {
-            flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN;
-        }
-        // Non-system uids are rate limited for POLL_ON_OPEN.
-        final int callingUid = Binder.getCallingUid();
-        flags = isRateLimitedForPoll(callingUid)
-                ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
-                : flags;
-        return flags;
-    }
-
-    private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
-        final int restrictedFlags = restrictFlagsForCaller(flags);
-        if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
-                | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                performPoll(FLAG_PERSIST_ALL);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        // return an IBinder which holds strong references to any loaded stats
-        // for its lifetime; when caller closes only weak references remain.
-
-        return new INetworkStatsSession.Stub() {
-            private final int mCallingUid = Binder.getCallingUid();
-            private final String mCallingPackage = callingPackage;
-            private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
-                    callingPackage);
-
-            private NetworkStatsCollection mUidComplete;
-            private NetworkStatsCollection mUidTagComplete;
-
-            private NetworkStatsCollection getUidComplete() {
-                synchronized (mStatsLock) {
-                    if (mUidComplete == null) {
-                        mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
-                    }
-                    return mUidComplete;
-                }
-            }
-
-            private NetworkStatsCollection getUidTagComplete() {
-                synchronized (mStatsLock) {
-                    if (mUidTagComplete == null) {
-                        mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
-                    }
-                    return mUidTagComplete;
-                }
-            }
-
-            @Override
-            public int[] getRelevantUids() {
-                return getUidComplete().getRelevantUids(mAccessLevel);
-            }
-
-            @Override
-            public NetworkStats getDeviceSummaryForNetwork(
-                    NetworkTemplate template, long start, long end) {
-                enforceTemplatePermissions(template, callingPackage);
-                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
-                        mAccessLevel, mCallingUid);
-            }
-
-            @Override
-            public NetworkStats getSummaryForNetwork(
-                    NetworkTemplate template, long start, long end) {
-                enforceTemplatePermissions(template, callingPackage);
-                return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
-                        mAccessLevel, mCallingUid);
-            }
-
-            // TODO: Remove this after all callers are removed.
-            @Override
-            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
-                enforceTemplatePermissions(template, callingPackage);
-                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
-                        mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
-            }
-
-            @Override
-            public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
-                    int fields, long start, long end) {
-                enforceTemplatePermissions(template, callingPackage);
-                // TODO(b/200768422): Redact returned history if the template is location
-                //  sensitive but the caller is not privileged.
-                return internalGetHistoryForNetwork(template, restrictedFlags, fields,
-                        mAccessLevel, mCallingUid, start, end);
-            }
-
-            @Override
-            public NetworkStats getSummaryForAllUid(
-                    NetworkTemplate template, long start, long end, boolean includeTags) {
-                enforceTemplatePermissions(template, callingPackage);
-                try {
-                    final NetworkStats stats = getUidComplete()
-                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
-                    if (includeTags) {
-                        final NetworkStats tagStats = getUidTagComplete()
-                                .getSummary(template, start, end, mAccessLevel, mCallingUid);
-                        stats.combineAllValues(tagStats);
-                    }
-                    return stats;
-                } catch (NullPointerException e) {
-                    throw e;
-                }
-            }
-
-            @Override
-            public NetworkStats getTaggedSummaryForAllUid(
-                    NetworkTemplate template, long start, long end) {
-                enforceTemplatePermissions(template, callingPackage);
-                try {
-                    final NetworkStats tagStats = getUidTagComplete()
-                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
-                    return tagStats;
-                } catch (NullPointerException e) {
-                    throw e;
-                }
-            }
-
-            @Override
-            public NetworkStatsHistory getHistoryForUid(
-                    NetworkTemplate template, int uid, int set, int tag, int fields) {
-                enforceTemplatePermissions(template, callingPackage);
-                // NOTE: We don't augment UID-level statistics
-                if (tag == TAG_NONE) {
-                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
-                            Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
-                } else {
-                    return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
-                            Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
-                }
-            }
-
-            @Override
-            public NetworkStatsHistory getHistoryIntervalForUid(
-                    NetworkTemplate template, int uid, int set, int tag, int fields,
-                    long start, long end) {
-                enforceTemplatePermissions(template, callingPackage);
-                // TODO(b/200768422): Redact returned history if the template is location
-                //  sensitive but the caller is not privileged.
-                // NOTE: We don't augment UID-level statistics
-                if (tag == TAG_NONE) {
-                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
-                            start, end, mAccessLevel, mCallingUid);
-                } else if (uid == Binder.getCallingUid()) {
-                    return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
-                            start, end, mAccessLevel, mCallingUid);
-                } else {
-                    throw new SecurityException("Calling package " + mCallingPackage
-                            + " cannot access tag information from a different uid");
-                }
-            }
-
-            @Override
-            public void close() {
-                mUidComplete = null;
-                mUidTagComplete = null;
-            }
-        };
-    }
-
-    private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
-            @NonNull String callingPackage) {
-        // For a template with wifi network keys, it is possible for a malicious
-        // client to track the user locations via querying data usage. Thus, enforce
-        // fine location permission check.
-        if (!template.getWifiNetworkKeys().isEmpty()) {
-            final boolean canAccessFineLocation = mLocationPermissionChecker
-                    .checkCallersLocationPermission(callingPackage,
-                    null /* featureId */,
-                            Binder.getCallingUid(),
-                            false /* coarseForTargetSdkLessThanQ */,
-                            null /* message */);
-            if (!canAccessFineLocation) {
-                throw new SecurityException("Access fine location is required when querying"
-                        + " with wifi network keys, make sure the app has the necessary"
-                        + "permissions and the location toggle is on.");
-            }
-        }
-    }
-
-    private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
-        return NetworkStatsAccess.checkAccessLevel(
-                mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
-    }
-
-    /**
-     * Find the most relevant {@link SubscriptionPlan} for the given
-     * {@link NetworkTemplate} and flags. This is typically used to augment
-     * local measurement results to match a known anchor from the carrier.
-     */
-    private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) {
-        SubscriptionPlan plan = null;
-        if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
-                && mSettings.getAugmentEnabled()) {
-            if (LOGD) Log.d(TAG, "Resolving plan for " + template);
-            final long token = Binder.clearCallingIdentity();
-            try {
-                plan = mContext.getSystemService(NetworkPolicyManager.class)
-                        .getSubscriptionPlan(template);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-            if (LOGD) Log.d(TAG, "Resolved to plan " + plan);
-        }
-        return plan;
-    }
-
-    /**
-     * Return network summary, splicing between DEV and XT stats when
-     * appropriate.
-     */
-    private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags,
-            long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
-        // We've been using pure XT stats long enough that we no longer need to
-        // splice DEV and XT together.
-        final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
-                accessLevel, callingUid, start, end);
-
-        final long now = System.currentTimeMillis();
-        final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
-
-        final NetworkStats stats = new NetworkStats(end - start, 1);
-        stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
-                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
-                entry.txBytes, entry.txPackets, entry.operations));
-        return stats;
-    }
-
-    /**
-     * Return network history, splicing between DEV and XT stats when
-     * appropriate.
-     */
-    private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
-            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
-            long start, long end) {
-        // We've been using pure XT stats long enough that we no longer need to
-        // splice DEV and XT together.
-        final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
-        synchronized (mStatsLock) {
-            return mXtStatsCached.getHistory(template, augmentPlan,
-                    UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
-        }
-    }
-
-    private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
-        assertSystemReady();
-
-        return internalGetSummaryForNetwork(template,
-                NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
-                NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
-    }
-
-    private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
-        assertSystemReady();
-
-        final NetworkStatsCollection uidComplete;
-        synchronized (mStatsLock) {
-            uidComplete = mUidRecorder.getOrLoadCompleteLocked();
-        }
-        return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE,
-                android.os.Process.SYSTEM_UID);
-    }
-
-    @Override
-    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
-        if (Binder.getCallingUid() != uid) {
-            Log.w(TAG, "Snapshots only available for calling UID");
-            return new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        }
-
-        // TODO: switch to data layer stats once kernel exports
-        // for now, read network layer stats and flatten across all ifaces.
-        // This function is used to query NeworkStats for calle's uid. The only caller method
-        // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query
-        // its own NetworkStats.
-        final long ident = Binder.clearCallingIdentity();
-        final NetworkStats networkLayer;
-        try {
-            networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-
-        // splice in operation counts
-        networkLayer.spliceOperationsFrom(mUidOperations);
-
-        final NetworkStats dataLayer = new NetworkStats(
-                networkLayer.getElapsedRealtime(), networkLayer.size());
-
-        NetworkStats.Entry entry = null;
-        for (int i = 0; i < networkLayer.size(); i++) {
-            entry = networkLayer.getValues(i, entry);
-            entry.iface = IFACE_ALL;
-            dataLayer.combineValues(entry);
-        }
-
-        return dataLayer;
-    }
-
-    @Override
-    public NetworkStats getUidStatsForTransport(int transport) {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-        try {
-            final String[] relevantIfaces =
-                    transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
-            // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
-            // interfaces, so this is not useful, remove it.
-            final String[] ifacesToQuery =
-                    mStatsFactory.augmentWithStackedInterfaces(relevantIfaces);
-            return getNetworkStatsUidDetail(ifacesToQuery);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error compiling UID stats", e);
-            return new NetworkStats(0L, 0);
-        }
-    }
-
-    @Override
-    public String[] getMobileIfaces() {
-        // TODO (b/192758557): Remove debug log.
-        if (CollectionUtils.contains(mMobileIfaces, null)) {
-            throw new NullPointerException(
-                    "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
-        }
-        return mMobileIfaces.clone();
-    }
-
-    @Override
-    public void incrementOperationCount(int uid, int tag, int operationCount) {
-        if (Binder.getCallingUid() != uid) {
-            mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
-        }
-
-        if (operationCount < 0) {
-            throw new IllegalArgumentException("operation count can only be incremented");
-        }
-        if (tag == TAG_NONE) {
-            throw new IllegalArgumentException("operation count must have specific tag");
-        }
-
-        synchronized (mStatsLock) {
-            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
-            mUidOperations.combineValues(
-                    mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
-            mUidOperations.combineValues(
-                    mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
-        }
-    }
-
-    private void setKernelCounterSet(int uid, int set) {
-        if (mUidCounterSetMap == null) {
-            Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map");
-            return;
-        }
-
-        if (set == SET_DEFAULT) {
-            try {
-                mUidCounterSetMap.deleteEntry(new U32(uid));
-            } catch (ErrnoException e) {
-                Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e);
-            }
-            return;
-        }
-
-        try {
-            mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set));
-        } catch (ErrnoException e) {
-            Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set
-                    + ") failed with errno: " + e);
-        }
-    }
-
-    @VisibleForTesting
-    public void noteUidForeground(int uid, boolean uidForeground) {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-        synchronized (mStatsLock) {
-            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
-            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
-            if (oldSet != set) {
-                mActiveUidCounterSet.put(uid, set);
-                setKernelCounterSet(uid, set);
-            }
-        }
-    }
-
-    /**
-     * Notify {@code NetworkStatsService} about network status changed.
-     */
-    public void notifyNetworkStatus(
-            @NonNull Network[] defaultNetworks,
-            @NonNull NetworkStateSnapshot[] networkStates,
-            @Nullable String activeIface,
-            @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        // Update the VPN underlying interfaces only after the poll is made and tun data has been
-        // migrated. Otherwise the migration would use the new interfaces instead of the ones that
-        // were current when the polled data was transferred.
-        mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
-    }
-
-    @Override
-    public void forceUpdate() {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            performPoll(FLAG_PERSIST_ALL);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    /** Advise persistence threshold; may be overridden internally. */
-    public void advisePersistThreshold(long thresholdBytes) {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-        // clamp threshold into safe range
-        mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes,
-                128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
-        if (LOGV) {
-            Log.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
-                    + mPersistThreshold);
-        }
-
-        final long oldGlobalAlertBytes = mGlobalAlertBytes;
-
-        // update and persist if beyond new thresholds
-        final long currentTime = mClock.millis();
-        synchronized (mStatsLock) {
-            if (!mSystemReady) return;
-
-            updatePersistThresholdsLocked();
-
-            mDevRecorder.maybePersistLocked(currentTime);
-            mXtRecorder.maybePersistLocked(currentTime);
-            mUidRecorder.maybePersistLocked(currentTime);
-            mUidTagRecorder.maybePersistLocked(currentTime);
-        }
-
-        if (oldGlobalAlertBytes != mGlobalAlertBytes) {
-            registerGlobalAlert();
-        }
-    }
-
-    @Override
-    public DataUsageRequest registerUsageCallback(@NonNull String callingPackage,
-                @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) {
-        Objects.requireNonNull(callingPackage, "calling package is null");
-        Objects.requireNonNull(request, "DataUsageRequest is null");
-        Objects.requireNonNull(request.template, "NetworkTemplate is null");
-        Objects.requireNonNull(callback, "callback is null");
-
-        int callingUid = Binder.getCallingUid();
-        @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
-        DataUsageRequest normalizedRequest;
-        final long token = Binder.clearCallingIdentity();
-        try {
-            normalizedRequest = mStatsObservers.register(mContext,
-                    request, callback, callingUid, accessLevel);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-
-        // Create baseline stats
-        mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL));
-
-        return normalizedRequest;
-   }
-
-    @Override
-    public void unregisterUsageRequest(DataUsageRequest request) {
-        Objects.requireNonNull(request, "DataUsageRequest is null");
-
-        int callingUid = Binder.getCallingUid();
-        final long token = Binder.clearCallingIdentity();
-        try {
-            mStatsObservers.unregister(request, callingUid);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    @Override
-    public long getUidStats(int uid, int type) {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
-            return UNSUPPORTED;
-        }
-        return nativeGetUidStat(uid, type);
-    }
-
-    @Override
-    public long getIfaceStats(@NonNull String iface, int type) {
-        Objects.requireNonNull(iface);
-        long nativeIfaceStats = nativeGetIfaceStat(iface, type);
-        if (nativeIfaceStats == -1) {
-            return nativeIfaceStats;
-        } else {
-            // When tethering offload is in use, nativeIfaceStats does not contain usage from
-            // offload, add it back here. Note that the included statistics might be stale
-            // since polling newest stats from hardware might impact system health and not
-            // suitable for TrafficStats API use cases.
-            return nativeIfaceStats + getProviderIfaceStats(iface, type);
-        }
-    }
-
-    @Override
-    public long getTotalStats(int type) {
-        long nativeTotalStats = nativeGetTotalStat(type);
-        if (nativeTotalStats == -1) {
-            return nativeTotalStats;
-        } else {
-            // Refer to comment in getIfaceStats
-            return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
-        }
-    }
-
-    private long getProviderIfaceStats(@Nullable String iface, int type) {
-        final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
-        final HashSet<String> limitIfaces;
-        if (iface == IFACE_ALL) {
-            limitIfaces = null;
-        } else {
-            limitIfaces = new HashSet<>();
-            limitIfaces.add(iface);
-        }
-        final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
-        switch (type) {
-            case TrafficStats.TYPE_RX_BYTES:
-                return entry.rxBytes;
-            case TrafficStats.TYPE_RX_PACKETS:
-                return entry.rxPackets;
-            case TrafficStats.TYPE_TX_BYTES:
-                return entry.txBytes;
-            case TrafficStats.TYPE_TX_PACKETS:
-                return entry.txPackets;
-            default:
-                return 0;
-        }
-    }
-
-    /**
-     * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
-     * reflect current {@link #mPersistThreshold} value. Always defers to
-     * {@link Global} values when defined.
-     */
-    @GuardedBy("mStatsLock")
-    private void updatePersistThresholdsLocked() {
-        mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
-        mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
-        mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
-        mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
-        mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
-    }
-
-    /**
-     * Listener that watches for {@link TetheringManager} to claim interface pairs.
-     */
-    private final TetheringManager.TetheringEventCallback mTetherListener =
-            new TetheringManager.TetheringEventCallback() {
-                @Override
-                public void onUpstreamChanged(@Nullable Network network) {
-                    performPoll(FLAG_PERSIST_NETWORK);
-                }
-            };
-
-    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and verified UPDATE_DEVICE_STATS
-            // permission above.
-            performPoll(FLAG_PERSIST_ALL);
-
-            // verify that we're watching global alert
-            registerGlobalAlert();
-        }
-    };
-
-    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and UID_REMOVED is protected
-            // broadcast.
-
-            final int uid = intent.getIntExtra(EXTRA_UID, -1);
-            if (uid == -1) return;
-
-            synchronized (mStatsLock) {
-                mWakeLock.acquire();
-                try {
-                    removeUidsLocked(uid);
-                } finally {
-                    mWakeLock.release();
-                }
-            }
-        }
-    };
-
-    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // On background handler thread, and USER_REMOVED is protected
-            // broadcast.
-
-            final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
-            if (userHandle == null) return;
-
-            synchronized (mStatsLock) {
-                mWakeLock.acquire();
-                try {
-                    removeUserLocked(userHandle);
-                } finally {
-                    mWakeLock.release();
-                }
-            }
-        }
-    };
-
-    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // SHUTDOWN is protected broadcast.
-            synchronized (mStatsLock) {
-                shutdownLocked();
-            }
-        }
-    };
-
-    /**
-     * Handle collapsed RAT type changed event.
-     */
-    @VisibleForTesting
-    public void handleOnCollapsedRatTypeChanged() {
-        // Protect service from frequently updating. Remove pending messages if any.
-        mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS);
-        mHandler.sendMessageDelayed(
-                mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay());
-    }
-
-    private void handleNotifyNetworkStatus(
-            Network[] defaultNetworks,
-            NetworkStateSnapshot[] snapshots,
-            String activeIface) {
-        synchronized (mStatsLock) {
-            mWakeLock.acquire();
-            try {
-                mActiveIface = activeIface;
-                handleNotifyNetworkStatusLocked(defaultNetworks, snapshots);
-            } finally {
-                mWakeLock.release();
-            }
-        }
-    }
-
-    /**
-     * Inspect all current {@link NetworkStateSnapshot}s to derive mapping from {@code iface} to
-     * {@link NetworkStatsHistory}. When multiple networks are active on a single {@code iface},
-     * they are combined under a single {@link NetworkIdentitySet}.
-     */
-    @GuardedBy("mStatsLock")
-    private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
-            @NonNull NetworkStateSnapshot[] snapshots) {
-        if (!mSystemReady) return;
-        if (LOGV) Log.v(TAG, "handleNotifyNetworkStatusLocked()");
-
-        // take one last stats snapshot before updating iface mapping. this
-        // isn't perfect, since the kernel may already be counting traffic from
-        // the updated network.
-
-        // poll, but only persist network stats to keep codepath fast. UID stats
-        // will be persisted during next alarm poll event.
-        performPollLocked(FLAG_PERSIST_NETWORK);
-
-        // Rebuild active interfaces based on connected networks
-        mActiveIfaces.clear();
-        mActiveUidIfaces.clear();
-        // Update the list of default networks.
-        mDefaultNetworks = defaultNetworks;
-
-        mLastNetworkStateSnapshots = snapshots;
-
-        final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
-        final ArraySet<String> mobileIfaces = new ArraySet<>();
-        final ArraySet<String> wifiIfaces = new ArraySet<>();
-        for (NetworkStateSnapshot snapshot : snapshots) {
-            final int displayTransport =
-                    getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
-            final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
-            final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
-            final boolean isDefault = CollectionUtils.contains(
-                    mDefaultNetworks, snapshot.getNetwork());
-            final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL
-                    : getRatTypeForStateSnapshot(snapshot);
-            final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
-                    isDefault, ratType);
-
-            // Traffic occurring on the base interface is always counted for
-            // both total usage and UID details.
-            final String baseIface = snapshot.getLinkProperties().getInterfaceName();
-            if (baseIface != null) {
-                findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
-                findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
-
-                // Build a separate virtual interface for VT (Video Telephony) data usage.
-                // Only do this when IMS is not metered, but VT is metered.
-                // If IMS is metered, then the IMS network usage has already included VT usage.
-                // VT is considered always metered in framework's layer. If VT is not metered
-                // per carrier's policy, modem will report 0 usage for VT calls.
-                if (snapshot.getNetworkCapabilities().hasCapability(
-                        NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
-
-                    // Copy the identify from IMS one but mark it as metered.
-                    NetworkIdentity vtIdent = new NetworkIdentity.Builder()
-                            .setType(ident.getType())
-                            .setRatType(ident.getRatType())
-                            .setSubscriberId(ident.getSubscriberId())
-                            .setWifiNetworkKey(ident.getWifiNetworkKey())
-                            .setRoaming(ident.isRoaming()).setMetered(true)
-                            .setDefaultNetwork(true)
-                            .setOemManaged(ident.getOemManaged())
-                            .setSubId(ident.getSubId()).build();
-                    final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
-                    findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
-                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
-                }
-
-                if (isMobile) {
-                    mobileIfaces.add(baseIface);
-                }
-                if (isWifi) {
-                    wifiIfaces.add(baseIface);
-                }
-            }
-
-            // Traffic occurring on stacked interfaces is usually clatd.
-            //
-            // UID stats are always counted on the stacked interface and never on the base
-            // interface, because the packets on the base interface do not actually match
-            // application sockets (they're not IPv4) and thus the app uid is not known.
-            // For receive this is obvious: packets must be translated from IPv6 to IPv4
-            // before the application socket can be found.
-            // For transmit: either they go through the clat daemon which by virtue of going
-            // through userspace strips the original socket association during the IPv4 to
-            // IPv6 translation process, or they are offloaded by eBPF, which doesn't:
-            // However, on an ebpf device the accounting is done in cgroup ebpf hooks,
-            // which don't trigger again post ebpf translation.
-            // (as such stats accounted to the clat uid are ignored)
-            //
-            // Interface stats are more complicated.
-            //
-            // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus
-            // *all* statistics are collected by iptables on the stacked v4-* interface.
-            //
-            // Additionally for ingress all packets bound for the clat IPv6 address are dropped
-            // in ip6tables raw prerouting and thus even non-offloaded packets are only
-            // accounted for on the stacked interface.
-            //
-            // For egress, packets subject to eBPF offload never appear on the base interface
-            // and only appear on the stacked interface. Thus to ensure packets increment
-            // interface stats, we must collate data from stacked interfaces. For xt_qtaguid
-            // (or non eBPF offloaded) TX they would appear on both, however egress interface
-            // accounting is explicitly bypassed for traffic from the clat uid.
-            //
-            // TODO: This code might be combined to above code.
-            for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) {
-                // baseIface has been handled, so ignore it.
-                if (TextUtils.equals(baseIface, iface)) continue;
-                if (iface != null) {
-                    findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident);
-                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident);
-                    if (isMobile) {
-                        mobileIfaces.add(iface);
-                    }
-                    if (isWifi) {
-                        wifiIfaces.add(iface);
-                    }
-
-                    mStatsFactory.noteStackedIface(iface, baseIface);
-                }
-            }
-        }
-
-        mMobileIfaces = mobileIfaces.toArray(new String[0]);
-        mWifiIfaces = wifiIfaces.toArray(new String[0]);
-        // TODO (b/192758557): Remove debug log.
-        if (CollectionUtils.contains(mMobileIfaces, null)) {
-            throw new NullPointerException(
-                    "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
-        }
-        if (CollectionUtils.contains(mWifiIfaces, null)) {
-            throw new NullPointerException(
-                    "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces));
-        }
-    }
-
-    private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
-        if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
-            throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR");
-        }
-
-        final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier();
-        if (spec instanceof TelephonyNetworkSpecifier) {
-             return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
-        } else {
-            Log.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
-            return INVALID_SUBSCRIPTION_ID;
-        }
-    }
-
-    /**
-     * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
-     * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
-     * transport types do not actually fill this value.
-     */
-    private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
-        if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
-            return 0;
-        }
-
-        return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId());
-    }
-
-    private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
-            ArrayMap<K, NetworkIdentitySet> map, K key) {
-        NetworkIdentitySet ident = map.get(key);
-        if (ident == null) {
-            ident = new NetworkIdentitySet();
-            map.put(key, ident);
-        }
-        return ident;
-    }
-
-    @GuardedBy("mStatsLock")
-    private void recordSnapshotLocked(long currentTime) throws RemoteException {
-        // snapshot and record current counters; read UID stats first to
-        // avoid over counting dev stats.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
-        final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
-        final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
-        final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-
-        // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
-        // from stats providers that isn't already counted by dev and XT stats.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
-        final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        xtSnapshot.combineAllValues(providersnapshot);
-        devSnapshot.combineAllValues(providersnapshot);
-
-        // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
-        // can't be reattributed to responsible apps.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
-        mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
-        mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-
-        // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
-        mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
-        mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-
-        // We need to make copies of member fields that are sent to the observer to avoid
-        // a race condition between the service handler thread and the observer's
-        mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
-                new ArrayMap<>(mActiveUidIfaces), currentTime);
-    }
-
-    /**
-     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
-     * so we have baseline values without double-counting.
-     */
-    @GuardedBy("mStatsLock")
-    private void bootstrapStatsLocked() {
-        final long currentTime = mClock.millis();
-
-        try {
-            recordSnapshotLocked(currentTime);
-        } catch (IllegalStateException e) {
-            Log.w(TAG, "problem reading network stats: " + e);
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
-        }
-    }
-
-    private void performPoll(int flags) {
-        synchronized (mStatsLock) {
-            mWakeLock.acquire();
-
-            try {
-                performPollLocked(flags);
-            } finally {
-                mWakeLock.release();
-            }
-        }
-    }
-
-    /**
-     * Periodic poll operation, reading current statistics and recording into
-     * {@link NetworkStatsHistory}.
-     */
-    @GuardedBy("mStatsLock")
-    private void performPollLocked(int flags) {
-        if (!mSystemReady) return;
-        if (LOGV) Log.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
-        Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
-
-        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
-        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
-        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
-
-        performPollFromProvidersLocked();
-
-        // TODO: consider marking "untrusted" times in historical stats
-        final long currentTime = mClock.millis();
-
-        try {
-            recordSnapshotLocked(currentTime);
-        } catch (IllegalStateException e) {
-            Log.wtf(TAG, "problem reading network stats", e);
-            return;
-        } catch (RemoteException e) {
-            // ignored; service lives in system_server
-            return;
-        }
-
-        // persist any pending data depending on requested flags
-        Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
-        if (persistForce) {
-            mDevRecorder.forcePersistLocked(currentTime);
-            mXtRecorder.forcePersistLocked(currentTime);
-            mUidRecorder.forcePersistLocked(currentTime);
-            mUidTagRecorder.forcePersistLocked(currentTime);
-        } else {
-            if (persistNetwork) {
-                mDevRecorder.maybePersistLocked(currentTime);
-                mXtRecorder.maybePersistLocked(currentTime);
-            }
-            if (persistUid) {
-                mUidRecorder.maybePersistLocked(currentTime);
-                mUidTagRecorder.maybePersistLocked(currentTime);
-            }
-        }
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-
-        if (mSettings.getSampleEnabled()) {
-            // sample stats after each full poll
-            performSampleLocked();
-        }
-
-        // finally, dispatch updated event to any listeners
-        mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED));
-
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-    }
-
-    @GuardedBy("mStatsLock")
-    private void performPollFromProvidersLocked() {
-        // Request asynchronous stats update from all providers for next poll. And wait a bit of
-        // time to allow providers report-in given that normally binder call should be fast. Note
-        // that size of list might be changed because addition/removing at the same time. For
-        // addition, the stats of the missed provider can only be collected in next poll;
-        // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
-        // once that happened.
-        // TODO: request with a valid token.
-        Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
-        final int registeredCallbackCount = mStatsProviderCbList.size();
-        mStatsProviderSem.drainPermits();
-        invokeForAllStatsProviderCallbacks(
-                (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
-        try {
-            mStatsProviderSem.tryAcquire(registeredCallbackCount,
-                    MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            // Strictly speaking it's possible a provider happened to deliver between the timeout
-            // and the log, and that doesn't matter too much as this is just a debug log.
-            Log.d(TAG, "requestStatsUpdate - providers responded "
-                    + mStatsProviderSem.availablePermits()
-                    + "/" + registeredCallbackCount + " : " + e);
-        }
-        Trace.traceEnd(TRACE_TAG_NETWORK);
-    }
-
-    /**
-     * Sample recent statistics summary into {@link EventLog}.
-     */
-    @GuardedBy("mStatsLock")
-    private void performSampleLocked() {
-        // TODO: migrate trustedtime fixes to separate binary log events
-        final long currentTime = mClock.millis();
-
-        NetworkTemplate template;
-        NetworkStats.Entry devTotal;
-        NetworkStats.Entry xtTotal;
-        NetworkStats.Entry uidTotal;
-
-        // collect mobile sample
-        template = buildTemplateMobileWildcard();
-        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
-        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
-        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
-
-        EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE,
-                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
-                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
-                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                currentTime);
-
-        // collect wifi sample
-        template = buildTemplateWifiWildcard();
-        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
-        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
-        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
-
-        EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE,
-                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
-                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
-                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
-                currentTime);
-    }
-
-    // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
-    private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) {
-        if (e.errno != ENOENT) Log.e(TAG, msg, e);
-    }
-
-    private <K extends StatsMapKey, V extends StatsMapValue> void deleteStatsMapTagData(
-            IBpfMap<K, V> statsMap, int uid) {
-        try {
-            statsMap.forEach((key, value) -> {
-                if (key.uid == uid) {
-                    try {
-                        statsMap.deleteEntry(key);
-                    } catch (ErrnoException e) {
-                        logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")");
-                    }
-                }
-            });
-        } catch (ErrnoException e) {
-            Log.e(TAG, "FAILED to delete tag data from stats map", e);
-        }
-    }
-
-    /**
-     * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap
-     * @param uid
-     */
-    private void deleteKernelTagData(int uid) {
-        try {
-            mCookieTagMap.forEach((key, value) -> {
-                // If SkDestroyListener deletes the socket tag while this code is running,
-                // forEach will either restart iteration from the beginning or return null,
-                // depending on when the deletion happens.
-                // If it returns null, continue iteration to delete the data and in fact it would
-                // just iterate from first key because BpfMap#getNextKey would return first key
-                // if the current key is not exist.
-                if (value != null && value.uid == uid) {
-                    try {
-                        mCookieTagMap.deleteEntry(key);
-                    } catch (ErrnoException e) {
-                        logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")");
-                    }
-                }
-            });
-        } catch (ErrnoException e) {
-            Log.e(TAG, "Failed to delete tag data from cookie tag map", e);
-        }
-
-        deleteStatsMapTagData(mStatsMapA, uid);
-        deleteStatsMapTagData(mStatsMapB, uid);
-
-        try {
-            mUidCounterSetMap.deleteEntry(new U32(uid));
-        } catch (ErrnoException e) {
-            logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map");
-        }
-
-        try {
-            mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid));
-        } catch (ErrnoException e) {
-            logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map");
-        }
-    }
-
-    /**
-     * Clean up {@link #mUidRecorder} after UID is removed.
-     */
-    @GuardedBy("mStatsLock")
-    private void removeUidsLocked(int... uids) {
-        if (LOGV) Log.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
-
-        // Perform one last poll before removing
-        performPollLocked(FLAG_PERSIST_ALL);
-
-        mUidRecorder.removeUidsLocked(uids);
-        mUidTagRecorder.removeUidsLocked(uids);
-
-        // Clear kernel stats associated with UID
-        for (int uid : uids) {
-            deleteKernelTagData(uid);
-        }
-    }
-
-    /**
-     * Clean up {@link #mUidRecorder} after user is removed.
-     */
-    @GuardedBy("mStatsLock")
-    private void removeUserLocked(@NonNull UserHandle userHandle) {
-        if (LOGV) Log.v(TAG, "removeUserLocked() for UserHandle=" + userHandle);
-
-        // Build list of UIDs that we should clean up
-        final ArrayList<Integer> uids = new ArrayList<>();
-        final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
-                PackageManager.MATCH_ANY_USER
-                | PackageManager.MATCH_DISABLED_COMPONENTS);
-        for (ApplicationInfo app : apps) {
-            final int uid = userHandle.getUid(app.uid);
-            uids.add(uid);
-        }
-
-        removeUidsLocked(CollectionUtils.toIntArray(uids));
-    }
-
-    /**
-     * Set the warning and limit to all registered custom network stats providers.
-     * Note that invocation of any interface will be sent to all providers.
-     */
-    public void setStatsProviderWarningAndLimitAsync(
-            @NonNull String iface, long warning, long limit) {
-        PermissionUtils.enforceNetworkStackPermission(mContext);
-        if (LOGV) {
-            Log.v(TAG, "setStatsProviderWarningAndLimitAsync("
-                    + iface + "," + warning + "," + limit + ")");
-        }
-        invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
-                warning, limit));
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
-        if (!PermissionUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
-
-        long duration = DateUtils.DAY_IN_MILLIS;
-        final HashSet<String> argSet = new HashSet<String>();
-        for (String arg : args) {
-            argSet.add(arg);
-
-            if (arg.startsWith("--duration=")) {
-                try {
-                    duration = Long.parseLong(arg.substring(11));
-                } catch (NumberFormatException ignored) {
-                }
-            }
-        }
-
-        // usage: dumpsys netstats --full --uid --tag --poll --checkin
-        final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
-        final boolean checkin = argSet.contains("--checkin");
-        final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
-        final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
-        final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
-
-        final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, "  ");
-
-        synchronized (mStatsLock) {
-            if (args.length > 0 && "--proto".equals(args[0])) {
-                // In this case ignore all other arguments.
-                dumpProtoLocked(fd);
-                return;
-            }
-
-            if (poll) {
-                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
-                pw.println("Forced poll");
-                return;
-            }
-
-            if (checkin) {
-                final long end = System.currentTimeMillis();
-                final long start = end - duration;
-
-                pw.print("v1,");
-                pw.print(start / SECOND_IN_MILLIS); pw.print(',');
-                pw.print(end / SECOND_IN_MILLIS); pw.println();
-
-                pw.println("xt");
-                mXtRecorder.dumpCheckin(rawWriter, start, end);
-
-                if (includeUid) {
-                    pw.println("uid");
-                    mUidRecorder.dumpCheckin(rawWriter, start, end);
-                }
-                if (includeTag) {
-                    pw.println("tag");
-                    mUidTagRecorder.dumpCheckin(rawWriter, start, end);
-                }
-                return;
-            }
-
-            pw.println("Configs:");
-            pw.increaseIndent();
-            pw.print(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
-            pw.println();
-            pw.decreaseIndent();
-
-            pw.println("Active interfaces:");
-            pw.increaseIndent();
-            for (int i = 0; i < mActiveIfaces.size(); i++) {
-                pw.print("iface", mActiveIfaces.keyAt(i));
-                pw.print("ident", mActiveIfaces.valueAt(i));
-                pw.println();
-            }
-            pw.decreaseIndent();
-
-            pw.println("Active UID interfaces:");
-            pw.increaseIndent();
-            for (int i = 0; i < mActiveUidIfaces.size(); i++) {
-                pw.print("iface", mActiveUidIfaces.keyAt(i));
-                pw.print("ident", mActiveUidIfaces.valueAt(i));
-                pw.println();
-            }
-            pw.decreaseIndent();
-
-            // Get the top openSession callers
-            final SparseIntArray calls;
-            synchronized (mOpenSessionCallsPerUid) {
-                calls = mOpenSessionCallsPerUid.clone();
-            }
-
-            final int N = calls.size();
-            final long[] values = new long[N];
-            for (int j = 0; j < N; j++) {
-                values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
-            }
-            Arrays.sort(values);
-
-            pw.println("Top openSession callers (uid=count):");
-            pw.increaseIndent();
-            final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
-            for (int j = N - 1; j >= end; j--) {
-                final int uid = (int) (values[j] & 0xffffffff);
-                final int count = (int) (values[j] >> 32);
-                pw.print(uid); pw.print("="); pw.println(count);
-            }
-            pw.decreaseIndent();
-            pw.println();
-
-            pw.println("Stats Providers:");
-            pw.increaseIndent();
-            invokeForAllStatsProviderCallbacks((cb) -> {
-                pw.println(cb.mTag + " Xt:");
-                pw.increaseIndent();
-                pw.print(cb.getCachedStats(STATS_PER_IFACE).toString());
-                pw.decreaseIndent();
-                if (includeUid) {
-                    pw.println(cb.mTag + " Uid:");
-                    pw.increaseIndent();
-                    pw.print(cb.getCachedStats(STATS_PER_UID).toString());
-                    pw.decreaseIndent();
-                }
-            });
-            pw.decreaseIndent();
-
-            pw.println("Dev stats:");
-            pw.increaseIndent();
-            mDevRecorder.dumpLocked(pw, fullHistory);
-            pw.decreaseIndent();
-
-            pw.println("Xt stats:");
-            pw.increaseIndent();
-            mXtRecorder.dumpLocked(pw, fullHistory);
-            pw.decreaseIndent();
-
-            if (includeUid) {
-                pw.println("UID stats:");
-                pw.increaseIndent();
-                mUidRecorder.dumpLocked(pw, fullHistory);
-                pw.decreaseIndent();
-            }
-
-            if (includeTag) {
-                pw.println("UID tag stats:");
-                pw.increaseIndent();
-                mUidTagRecorder.dumpLocked(pw, fullHistory);
-                pw.decreaseIndent();
-            }
-        }
-    }
-
-    @GuardedBy("mStatsLock")
-    private void dumpProtoLocked(FileDescriptor fd) {
-        final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd));
-
-        // TODO Right now it writes all history.  Should it limit to the "since-boot" log?
-
-        dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES,
-                mActiveIfaces);
-        dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES,
-                mActiveUidIfaces);
-        mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
-        mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
-        mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
-        mUidTagRecorder.dumpDebugLocked(proto,
-                NetworkStatsServiceDumpProto.UID_TAG_STATS);
-
-        proto.flush();
-    }
-
-    private static void dumpInterfaces(ProtoOutputStream proto, long tag,
-            ArrayMap<String, NetworkIdentitySet> ifaces) {
-        for (int i = 0; i < ifaces.size(); i++) {
-            final long start = proto.start(tag);
-
-            proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
-            ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES);
-
-            proto.end(start);
-        }
-    }
-
-    private NetworkStats readNetworkStatsSummaryDev() {
-        try {
-            return mStatsFactory.readNetworkStatsSummaryDev();
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    private NetworkStats readNetworkStatsSummaryXt() {
-        try {
-            return mStatsFactory.readNetworkStatsSummaryXt();
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    private NetworkStats readNetworkStatsUidDetail(int uid, String[] ifaces, int tag) {
-        try {
-            return mStatsFactory.readNetworkStatsDetail(uid, ifaces, tag);
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    /**
-     * Return snapshot of current UID statistics, including any
-     * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
-     * values.
-     *
-     * @param ifaces A list of interfaces the stats should be restricted to, or
-     *               {@link NetworkStats#INTERFACES_ALL}.
-     */
-    private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
-            throws RemoteException {
-        final NetworkStats uidSnapshot = readNetworkStatsUidDetail(UID_ALL,  ifaces, TAG_ALL);
-
-        // fold tethering stats and operations into uid snapshot
-        final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
-        tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
-        mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
-        uidSnapshot.combineAllValues(tetherSnapshot);
-
-        // get a stale copy of uid stats snapshot provided by providers.
-        final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID);
-        providerStats.filter(UID_ALL, ifaces, TAG_ALL);
-        mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats);
-        uidSnapshot.combineAllValues(providerStats);
-
-        uidSnapshot.combineAllValues(mUidOperations);
-
-        return uidSnapshot;
-    }
-
-    /**
-     * Return snapshot of current non-offloaded tethering statistics. Will return empty
-     * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE}
-     * since it is already included by {@link #nativeGetIfaceStat}.
-     * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats.
-     */
-    // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
-    //  tethering stats.
-    private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
-         // We only need to return per-UID stats. Per-device stats are already counted by
-        // interface counters.
-        if (how != STATS_PER_UID) {
-            return new NetworkStats(SystemClock.elapsedRealtime(), 0);
-        }
-
-        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
-        try {
-            final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats();
-            for (TetherStatsParcel tetherStats : tetherStatsParcels) {
-                try {
-                    stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING,
-                            SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets,
-                            tetherStats.txBytes, tetherStats.txPackets, 0L));
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    throw new IllegalStateException("invalid tethering stats " + e);
-                }
-            }
-        } catch (IllegalStateException e) {
-            Log.wtf(TAG, "problem reading network stats", e);
-        }
-        return stats;
-    }
-
-    // TODO: It is copied from ConnectivityService, consider refactor these check permission
-    //  functions to a proper util.
-    private boolean checkAnyPermissionOf(String... permissions) {
-        for (String permission : permissions) {
-            if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void enforceAnyPermissionOf(String... permissions) {
-        if (!checkAnyPermissionOf(permissions)) {
-            throw new SecurityException("Requires one of the following permissions: "
-                    + String.join(", ", permissions) + ".");
-        }
-    }
-
-    /**
-     * Registers a custom provider of {@link android.net.NetworkStats} to combine the network
-     * statistics that cannot be seen by the kernel to system. To unregister, invoke the
-     * {@code unregister()} of the returned callback.
-     *
-     * @param tag a human readable identifier of the custom network stats provider.
-     * @param provider the {@link INetworkStatsProvider} binder corresponding to the
-     *                 {@link NetworkStatsProvider} to be registered.
-     *
-     * @return a {@link INetworkStatsProviderCallback} binder
-     *         interface, which can be used to report events to the system.
-     */
-    public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
-            @NonNull String tag, @NonNull INetworkStatsProvider provider) {
-        enforceAnyPermissionOf(NETWORK_STATS_PROVIDER,
-                NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
-        Objects.requireNonNull(provider, "provider is null");
-        Objects.requireNonNull(tag, "tag is null");
-        final NetworkPolicyManager netPolicyManager = mContext
-                .getSystemService(NetworkPolicyManager.class);
-        try {
-            NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
-                    tag, provider, mStatsProviderSem, mAlertObserver,
-                    mStatsProviderCbList, netPolicyManager);
-            mStatsProviderCbList.add(callback);
-            Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
-                    + getCallingUid() + "/" + getCallingPid());
-            return callback;
-        } catch (RemoteException e) {
-            Log.e(TAG, "registerNetworkStatsProvider failed", e);
-        }
-        return null;
-    }
-
-    // Collect stats from local cache of providers.
-    private @NonNull NetworkStats getNetworkStatsFromProviders(int how) {
-        final NetworkStats ret = new NetworkStats(0L, 0);
-        invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how)));
-        return ret;
-    }
-
-    @FunctionalInterface
-    private interface ThrowingConsumer<S, T extends Throwable> {
-        void accept(S s) throws T;
-    }
-
-    private void invokeForAllStatsProviderCallbacks(
-            @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) {
-        for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) {
-            try {
-                task.accept(cb);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
-            }
-        }
-    }
-
-    private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub
-            implements IBinder.DeathRecipient {
-        @NonNull final String mTag;
-
-        @NonNull final INetworkStatsProvider mProvider;
-        @NonNull private final Semaphore mSemaphore;
-        @NonNull final AlertObserver mAlertObserver;
-        @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
-        @NonNull final NetworkPolicyManager mNetworkPolicyManager;
-
-        @NonNull private final Object mProviderStatsLock = new Object();
-
-        @GuardedBy("mProviderStatsLock")
-        // Track STATS_PER_IFACE and STATS_PER_UID separately.
-        private final NetworkStats mIfaceStats = new NetworkStats(0L, 0);
-        @GuardedBy("mProviderStatsLock")
-        private final NetworkStats mUidStats = new NetworkStats(0L, 0);
-
-        NetworkStatsProviderCallbackImpl(
-                @NonNull String tag, @NonNull INetworkStatsProvider provider,
-                @NonNull Semaphore semaphore,
-                @NonNull AlertObserver alertObserver,
-                @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList,
-                @NonNull NetworkPolicyManager networkPolicyManager)
-                throws RemoteException {
-            mTag = tag;
-            mProvider = provider;
-            mProvider.asBinder().linkToDeath(this, 0);
-            mSemaphore = semaphore;
-            mAlertObserver = alertObserver;
-            mStatsProviderCbList = cbList;
-            mNetworkPolicyManager = networkPolicyManager;
-        }
-
-        @NonNull
-        public NetworkStats getCachedStats(int how) {
-            synchronized (mProviderStatsLock) {
-                NetworkStats stats;
-                switch (how) {
-                    case STATS_PER_IFACE:
-                        stats = mIfaceStats;
-                        break;
-                    case STATS_PER_UID:
-                        stats = mUidStats;
-                        break;
-                    default:
-                        throw new IllegalArgumentException("Invalid type: " + how);
-                }
-                // Callers might be able to mutate the returned object. Return a defensive copy
-                // instead of local reference.
-                return stats.clone();
-            }
-        }
-
-        @Override
-        public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
-                @Nullable NetworkStats uidStats) {
-            // TODO: 1. Use token to map ifaces to correct NetworkIdentity.
-            //       2. Store the difference and store it directly to the recorder.
-            synchronized (mProviderStatsLock) {
-                if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats);
-                if (uidStats != null) mUidStats.combineAllValues(uidStats);
-            }
-            mSemaphore.release();
-        }
-
-        @Override
-        public void notifyAlertReached() throws RemoteException {
-            // This binder object can only have been obtained by a process that holds
-            // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
-            BinderUtils.withCleanCallingIdentity(() ->
-                    mAlertObserver.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
-        }
-
-        @Override
-        public void notifyWarningReached() {
-            Log.d(TAG, mTag + ": notifyWarningReached");
-            BinderUtils.withCleanCallingIdentity(() ->
-                    mNetworkPolicyManager.notifyStatsProviderWarningReached());
-        }
-
-        @Override
-        public void notifyLimitReached() {
-            Log.d(TAG, mTag + ": notifyLimitReached");
-            BinderUtils.withCleanCallingIdentity(() ->
-                    mNetworkPolicyManager.notifyStatsProviderLimitReached());
-        }
-
-        @Override
-        public void binderDied() {
-            Log.d(TAG, mTag + ": binderDied");
-            mStatsProviderCbList.remove(this);
-        }
-
-        @Override
-        public void unregister() {
-            Log.d(TAG, mTag + ": unregister");
-            mStatsProviderCbList.remove(this);
-        }
-
-    }
-
-    private void assertSystemReady() {
-        if (!mSystemReady) {
-            throw new IllegalStateException("System not ready");
-        }
-    }
-
-    private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
-        @Override
-        public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
-                int rightIndex, String cookie) {
-            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
-
-            // record error for debugging
-            final StringBuilder builder = new StringBuilder();
-            builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
-                    + "] - right[" + rightIndex + "]\n");
-            builder.append("left=").append(left).append('\n');
-            builder.append("right=").append(right).append('\n');
-
-            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
-                    builder.toString());
-        }
-
-        @Override
-        public void foundNonMonotonic(
-                NetworkStats stats, int statsIndex, String cookie) {
-            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
-
-            final StringBuilder builder = new StringBuilder();
-            builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
-            builder.append("stats=").append(stats).append('\n');
-
-            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
-                    builder.toString());
-        }
-    }
-
-    /**
-     * Default external settings that read from
-     * {@link android.provider.Settings.Global}.
-     */
-    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
-        DefaultNetworkStatsSettings() {}
-
-        @Override
-        public long getPollInterval() {
-            return 30 * MINUTE_IN_MILLIS;
-        }
-        @Override
-        public long getPollDelay() {
-            return DEFAULT_PERFORM_POLL_DELAY_MS;
-        }
-        @Override
-        public long getGlobalAlertBytes(long def) {
-            return def;
-        }
-        @Override
-        public boolean getSampleEnabled() {
-            return true;
-        }
-        @Override
-        public boolean getAugmentEnabled() {
-            return true;
-        }
-        @Override
-        public boolean getCombineSubtypeEnabled() {
-            return false;
-        }
-        @Override
-        public Config getDevConfig() {
-            return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
-        }
-        @Override
-        public Config getXtConfig() {
-            return getDevConfig();
-        }
-        @Override
-        public Config getUidConfig() {
-            return new Config(2 * HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
-        }
-        @Override
-        public Config getUidTagConfig() {
-            return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS);
-        }
-        @Override
-        public long getDevPersistBytes(long def) {
-            return def;
-        }
-        @Override
-        public long getXtPersistBytes(long def) {
-            return def;
-        }
-        @Override
-        public long getUidPersistBytes(long def) {
-            return def;
-        }
-        @Override
-        public long getUidTagPersistBytes(long def) {
-            return def;
-        }
-    }
-
-    private static native long nativeGetTotalStat(int type);
-    private static native long nativeGetIfaceStat(String iface, int type);
-    private static native long nativeGetUidStat(int uid, int type);
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
deleted file mode 100644
index 65ccd20..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA;
-import static android.app.usage.NetworkStatsManager.getCollapsedRatType;
-import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
-import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
-import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
-
-import android.annotation.NonNull;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyCallback;
-import android.telephony.TelephonyDisplayInfo;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.net.module.util.CollectionUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-
-/**
- * Helper class that watches for events that are triggered per subscription.
- */
-@TargetApi(Build.VERSION_CODES.TIRAMISU)
-public class NetworkStatsSubscriptionsMonitor extends
-        SubscriptionManager.OnSubscriptionsChangedListener {
-
-    /**
-     * Interface that this monitor uses to delegate event handling to NetworkStatsService.
-     */
-    public interface Delegate {
-        /**
-         * Notify that the collapsed RAT type has been changed for any subscription. The method
-         * will also be triggered for any existing sub when start and stop monitoring.
-         *
-         * @param subscriberId IMSI of the subscription.
-         * @param collapsedRatType collapsed RAT type.
-         *                     @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int).
-         */
-        void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType);
-    }
-    private final Delegate mDelegate;
-
-    /**
-     * Receivers that watches for {@link TelephonyDisplayInfo} changes for each subscription, to
-     * monitor the transitioning between Radio Access Technology(RAT) types for each sub.
-     */
-    @NonNull
-    private final CopyOnWriteArrayList<RatTypeListener> mRatListeners =
-            new CopyOnWriteArrayList<>();
-
-    @NonNull
-    private final SubscriptionManager mSubscriptionManager;
-    @NonNull
-    private final TelephonyManager mTeleManager;
-
-    @NonNull
-    private final Executor mExecutor;
-
-    NetworkStatsSubscriptionsMonitor(@NonNull Context context,
-            @NonNull Executor executor, @NonNull Delegate delegate) {
-        super();
-        mSubscriptionManager = (SubscriptionManager) context.getSystemService(
-                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-        mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        mExecutor = executor;
-        mDelegate = delegate;
-    }
-
-    @Override
-    public void onSubscriptionsChanged() {
-        // Collect active subId list, hidden subId such as opportunistic subscriptions are
-        // also needed to track CBRS.
-        final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
-
-        // IMSI is needed for every newly added sub. Listener stores subscriberId into it to
-        // prevent binder call to telephony when querying RAT. Keep listener registration with empty
-        // IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported
-        // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration.
-        final List<Pair<Integer, String>> filteredNewSubs = new ArrayList<>();
-        for (final int subId : newSubs) {
-            final String subscriberId =
-                    mTeleManager.createForSubscriptionId(subId).getSubscriberId();
-            if (!TextUtils.isEmpty(subscriberId)) {
-                filteredNewSubs.add(new Pair(subId, subscriberId));
-            }
-        }
-
-        for (final Pair<Integer, String> sub : filteredNewSubs) {
-            // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be
-            // suddenly change regardless of subId, such as switch IMSI feature in modem side.
-            // If that happens, register new listener with new IMSI and remove old one later.
-            if (CollectionUtils.any(mRatListeners, it -> it.equalsKey(sub.first, sub.second))) {
-                continue;
-            }
-
-            final RatTypeListener listener = new RatTypeListener(this, sub.first, sub.second);
-            mRatListeners.add(listener);
-
-            // Register listener to the telephony manager that associated with specific sub.
-            mTeleManager.createForSubscriptionId(sub.first)
-                    .registerTelephonyCallback(mExecutor, listener);
-            Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
-        }
-
-        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
-            // If there is no subId and IMSI matched the listener, removes it.
-            if (!CollectionUtils.any(filteredNewSubs,
-                    it -> listener.equalsKey(it.first, it.second))) {
-                handleRemoveRatTypeListener(listener);
-            }
-        }
-    }
-
-    @NonNull
-    private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) {
-        final ArrayList<Integer> ret = new ArrayList<>();
-        final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList();
-        for (int id : ids) ret.add(id);
-        return ret;
-    }
-
-    /**
-     * Get a collapsed RatType for the given subscriberId.
-     *
-     * @param subscriberId the target subscriberId
-     * @return collapsed RatType for the given subscriberId
-     */
-    public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
-        final int index = CollectionUtils.indexOf(mRatListeners,
-                it -> TextUtils.equals(subscriberId, it.mSubscriberId));
-        return index != -1 ? mRatListeners.get(index).mLastCollapsedRatType
-                : TelephonyManager.NETWORK_TYPE_UNKNOWN;
-    }
-
-    /**
-     * Start monitoring events that triggered per subscription.
-     */
-    public void start() {
-        mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this);
-    }
-
-    /**
-     * Unregister subscription changes and all listeners for each subscription.
-     */
-    public void stop() {
-        mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
-
-        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
-            handleRemoveRatTypeListener(listener);
-        }
-    }
-
-    private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
-        mTeleManager.createForSubscriptionId(listener.mSubId)
-                .unregisterTelephonyCallback(listener);
-        Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
-        mRatListeners.remove(listener);
-
-        // Removal of subscriptions doesn't generate RAT changed event, fire it for every
-        // RatTypeListener.
-        mDelegate.onCollapsedRatTypeChanged(
-                listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
-    }
-
-    static class RatTypeListener extends TelephonyCallback
-            implements TelephonyCallback.DisplayInfoListener {
-        // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
-        @NonNull
-        private final int mSubId;
-
-        // IMSI to identifying the corresponding network from {@link NetworkState}.
-        // See {@link TelephonyManager#getSubscriberId}.
-        @NonNull
-        private final String mSubscriberId;
-
-        private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-        @NonNull
-        private final NetworkStatsSubscriptionsMonitor mMonitor;
-
-        RatTypeListener(@NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
-                @NonNull String subscriberId) {
-            mSubId = subId;
-            mSubscriberId = subscriberId;
-            mMonitor = monitor;
-        }
-
-        @Override
-        public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
-            // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
-            // would report RAT = 5G_NR.
-            // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
-            // network allocates a secondary 5G cell so telephony reports RAT = LTE along with
-            // NR state as connected. In such case, attributes the data usage to NR.
-            // See b/160727498.
-            final boolean is5GNsa = displayInfo.getNetworkType() == NETWORK_TYPE_LTE
-                    && (displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_NSA
-                    || displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
-
-            final int networkType =
-                    (is5GNsa ? NETWORK_TYPE_5G_NSA : displayInfo.getNetworkType());
-            final int collapsedRatType = getCollapsedRatType(networkType);
-            if (collapsedRatType == mLastCollapsedRatType) return;
-
-            if (NetworkStatsService.LOGD) {
-                Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): "
-                        + mLastCollapsedRatType + " -> " + collapsedRatType);
-            }
-            mLastCollapsedRatType = collapsedRatType;
-            mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType);
-        }
-
-        @VisibleForTesting
-        public int getSubId() {
-            return mSubId;
-        }
-
-        boolean equalsKey(int subId, @NonNull String subscriberId) {
-            return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId);
-        }
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
deleted file mode 100644
index ea8d836..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for both stats maps.
- */
-public class StatsMapKey extends Struct {
-    @Field(order = 0, type = Type.U32)
-    public final long uid;
-
-    @Field(order = 1, type = Type.U32)
-    public final long tag;
-
-    @Field(order = 2, type = Type.U32)
-    public final long counterSet;
-
-    @Field(order = 3, type = Type.U32)
-    public final long ifaceIndex;
-
-    public StatsMapKey(final long uid, final long tag, final long counterSet,
-            final long ifaceIndex) {
-        this.uid = uid;
-        this.tag = tag;
-        this.counterSet = counterSet;
-        this.ifaceIndex = ifaceIndex;
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
deleted file mode 100644
index 48f26ce..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Value used for both stats maps and uid stats map.
- */
-public class StatsMapValue extends Struct {
-    @Field(order = 0, type = Type.U63)
-    public final long rxPackets;
-
-    @Field(order = 1, type = Type.U63)
-    public final long rxBytes;
-
-    @Field(order = 2, type = Type.U63)
-    public final long txPackets;
-
-    @Field(order = 3, type = Type.U63)
-    public final long txBytes;
-
-    public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets,
-            final long txBytes) {
-        this.rxPackets = rxPackets;
-        this.rxBytes = rxBytes;
-        this.txPackets = txPackets;
-        this.txBytes = txBytes;
-    }
-}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
deleted file mode 100644
index 2849f94..0000000
--- a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.server.net;
-
-import com.android.net.module.util.Struct;
-import com.android.net.module.util.Struct.Field;
-import com.android.net.module.util.Struct.Type;
-
-/**
- * Key for uid stats map.
- */
-public class UidStatsMapKey extends Struct {
-    @Field(order = 0, type = Type.U32)
-    public final long uid;
-
-    public UidStatsMapKey(final long uid) {
-        this.uid = uid;
-    }
-}
diff --git a/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
deleted file mode 100644
index e2253a2..0000000
--- a/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import static com.android.server.NativeDaemonConnector.appendEscaped;
-import static com.android.server.NativeDaemonConnector.makeCommand;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-
-import com.android.server.NativeDaemonConnector.SensitiveArg;
-
-/**
- * Tests for {@link NativeDaemonConnector}.
- */
-@MediumTest
-public class NativeDaemonConnectorTest extends AndroidTestCase {
-    private static final String TAG = "NativeDaemonConnectorTest";
-
-    public void testArgumentNormal() throws Exception {
-        final StringBuilder builder = new StringBuilder();
-
-        builder.setLength(0);
-        appendEscaped(builder, "");
-        assertEquals("", builder.toString());
-
-        builder.setLength(0);
-        appendEscaped(builder, "foo");
-        assertEquals("foo", builder.toString());
-
-        builder.setLength(0);
-        appendEscaped(builder, "foo\"bar");
-        assertEquals("foo\\\"bar", builder.toString());
-
-        builder.setLength(0);
-        appendEscaped(builder, "foo\\bar\\\"baz");
-        assertEquals("foo\\\\bar\\\\\\\"baz", builder.toString());
-    }
-
-    public void testArgumentWithSpaces() throws Exception {
-        final StringBuilder builder = new StringBuilder();
-
-        builder.setLength(0);
-        appendEscaped(builder, "foo bar");
-        assertEquals("\"foo bar\"", builder.toString());
-
-        builder.setLength(0);
-        appendEscaped(builder, "foo\"bar\\baz foo");
-        assertEquals("\"foo\\\"bar\\\\baz foo\"", builder.toString());
-    }
-
-    public void testArgumentWithUtf() throws Exception {
-        final StringBuilder builder = new StringBuilder();
-
-        builder.setLength(0);
-        appendEscaped(builder, "caf\u00E9 c\u00F6ffee");
-        assertEquals("\"caf\u00E9 c\u00F6ffee\"", builder.toString());
-    }
-
-    public void testSensitiveArgs() throws Exception {
-        final StringBuilder rawBuilder = new StringBuilder();
-        final StringBuilder logBuilder = new StringBuilder();
-
-        rawBuilder.setLength(0);
-        logBuilder.setLength(0);
-        makeCommand(rawBuilder, logBuilder, 1, "foo", "bar", "baz");
-        assertEquals("1 foo bar baz\0", rawBuilder.toString());
-        assertEquals("1 foo bar baz", logBuilder.toString());
-
-        rawBuilder.setLength(0);
-        logBuilder.setLength(0);
-        makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("bar"), "baz");
-        assertEquals("1 foo bar baz\0", rawBuilder.toString());
-        assertEquals("1 foo [scrubbed] baz", logBuilder.toString());
-
-        rawBuilder.setLength(0);
-        logBuilder.setLength(0);
-        makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("foo bar"), "baz baz",
-                new SensitiveArg("wat"));
-        assertEquals("1 foo \"foo bar\" \"baz baz\" wat\0", rawBuilder.toString());
-        assertEquals("1 foo [scrubbed] \"baz baz\" [scrubbed]", logBuilder.toString());
-    }
-}
diff --git a/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
deleted file mode 100644
index ad0be58..0000000
--- a/packages/ConnectivityT/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.net;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-import android.net.InetAddresses;
-import android.net.IpConfiguration;
-import android.net.IpConfiguration.IpAssignment;
-import android.net.IpConfiguration.ProxySettings;
-import android.net.LinkAddress;
-import android.net.ProxyInfo;
-import android.net.StaticIpConfiguration;
-import android.util.ArrayMap;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Unit tests for {@link IpConfigStore}
- */
-@RunWith(AndroidJUnit4.class)
-public class IpConfigStoreTest {
-    private static final int KEY_CONFIG = 17;
-    private static final String IFACE_1 = "eth0";
-    private static final String IFACE_2 = "eth1";
-    private static final String IP_ADDR_1 = "192.168.1.10/24";
-    private static final String IP_ADDR_2 = "192.168.1.20/24";
-    private static final String DNS_IP_ADDR_1 = "1.2.3.4";
-    private static final String DNS_IP_ADDR_2 = "5.6.7.8";
-
-    @Test
-    public void backwardCompatibility2to3() throws IOException {
-        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
-        DataOutputStream outputStream = new DataOutputStream(byteStream);
-
-        final IpConfiguration expectedConfig =
-                newIpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
-
-        // Emulate writing to old format.
-        writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig);
-
-        InputStream in = new ByteArrayInputStream(byteStream.toByteArray());
-        ArrayMap<String, IpConfiguration> configurations = IpConfigStore.readIpConfigurations(in);
-
-        assertNotNull(configurations);
-        assertEquals(1, configurations.size());
-        IpConfiguration actualConfig = configurations.get(String.valueOf(KEY_CONFIG));
-        assertNotNull(actualConfig);
-        assertEquals(expectedConfig, actualConfig);
-    }
-
-    @Test
-    public void staticIpMultiNetworks() throws Exception {
-        final ArrayList<InetAddress> dnsServers = new ArrayList<>();
-        dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1));
-        dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2));
-        final StaticIpConfiguration staticIpConfiguration1 = new StaticIpConfiguration.Builder()
-                .setIpAddress(new LinkAddress(IP_ADDR_1))
-                .setDnsServers(dnsServers).build();
-        final StaticIpConfiguration staticIpConfiguration2 = new StaticIpConfiguration.Builder()
-                .setIpAddress(new LinkAddress(IP_ADDR_2))
-                .setDnsServers(dnsServers).build();
-
-        ProxyInfo proxyInfo =
-                ProxyInfo.buildDirectProxy("10.10.10.10", 88, Arrays.asList("host1", "host2"));
-
-        IpConfiguration expectedConfig1 = newIpConfiguration(IpAssignment.STATIC,
-                ProxySettings.STATIC, staticIpConfiguration1, proxyInfo);
-        IpConfiguration expectedConfig2 = newIpConfiguration(IpAssignment.STATIC,
-                ProxySettings.STATIC, staticIpConfiguration2, proxyInfo);
-
-        ArrayMap<String, IpConfiguration> expectedNetworks = new ArrayMap<>();
-        expectedNetworks.put(IFACE_1, expectedConfig1);
-        expectedNetworks.put(IFACE_2, expectedConfig2);
-
-        MockedDelayedDiskWrite writer = new MockedDelayedDiskWrite();
-        IpConfigStore store = new IpConfigStore(writer);
-        store.writeIpConfigurations("file/path/not/used/", expectedNetworks);
-
-        InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray());
-        ArrayMap<String, IpConfiguration> actualNetworks = IpConfigStore.readIpConfigurations(in);
-        assertNotNull(actualNetworks);
-        assertEquals(2, actualNetworks.size());
-        assertEquals(expectedNetworks.get(IFACE_1), actualNetworks.get(IFACE_1));
-        assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2));
-    }
-
-    private IpConfiguration newIpConfiguration(IpAssignment ipAssignment,
-            ProxySettings proxySettings, StaticIpConfiguration staticIpConfig, ProxyInfo info) {
-        final IpConfiguration config = new IpConfiguration();
-        config.setIpAssignment(ipAssignment);
-        config.setProxySettings(proxySettings);
-        config.setStaticIpConfiguration(staticIpConfig);
-        config.setHttpProxy(info);
-        return config;
-    }
-
-    // This is simplified snapshot of code that was used to store values in V2 format (key as int).
-    private static void writeDhcpConfigV2(DataOutputStream out, int configKey,
-            IpConfiguration config) throws IOException {
-        out.writeInt(2);  // VERSION 2
-        switch (config.getIpAssignment()) {
-            case DHCP:
-                out.writeUTF("ipAssignment");
-                out.writeUTF(config.getIpAssignment().toString());
-                break;
-            default:
-                fail("Not supported in test environment");
-        }
-
-        out.writeUTF("id");
-        out.writeInt(configKey);
-        out.writeUTF("eos");
-    }
-
-    /** Synchronously writes into given byte steam */
-    private static class MockedDelayedDiskWrite extends DelayedDiskWrite {
-        final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
-
-        @Override
-        public void write(String filePath, Writer w) {
-            DataOutputStream outputStream = new DataOutputStream(mByteStream);
-
-            try {
-                w.onWriteCalled(outputStream);
-            } catch (IOException e) {
-                fail();
-            }
-        }
-    }
-}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 02128d4..3a35659 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -112,18 +112,20 @@
     private static final int EVENT_DSU_INSTALL_FAILED = 120002;
 
     protected static void logEventProgressUpdate(
-            String partition,
-            long installedSize,
-            long partitionSize,
+            String partitionName,
+            long installedBytes,
+            long totalBytes,
             int partitionNumber,
-            int totalPartitionNumber) {
+            int totalPartitionNumber,
+            int totalProgressPercentage) {
         EventLog.writeEvent(
                 EVENT_DSU_PROGRESS_UPDATE,
-                partition,
-                installedSize,
-                partitionSize,
+                partitionName,
+                installedBytes,
+                totalBytes,
                 partitionNumber,
-                totalPartitionNumber);
+                totalPartitionNumber,
+                totalProgressPercentage);
     }
 
     protected static void logEventComplete() {
@@ -231,10 +233,11 @@
     public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
         logEventProgressUpdate(
                 progress.partitionName,
-                progress.installedSize,
-                progress.partitionSize,
+                progress.installedBytes,
+                progress.totalBytes,
                 progress.partitionNumber,
-                progress.totalPartitionNumber);
+                progress.totalPartitionNumber,
+                progress.totalProgressPercentage);
 
         mInstallTaskProgress = progress;
         postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
@@ -483,23 +486,46 @@
 
         switch (status) {
             case STATUS_IN_PROGRESS:
-                builder.setContentText(getString(R.string.notification_install_inprogress));
+                String msgInProgress = getString(R.string.notification_install_inprogress);
 
-                if (mInstallTaskProgress != null) {
-                    int max = 1024;
-                    int progress = 0;
+                if (mInstallTaskProgress == null) {
+                    builder.setContentText(msgInProgress);
+                } else {
+                    if (mInstallTaskProgress.totalPartitionNumber > 0) {
+                        builder.setContentText(
+                                String.format(
+                                        "%s: %s partition [%d/%d]",
+                                        msgInProgress,
+                                        mInstallTaskProgress.partitionName,
+                                        mInstallTaskProgress.partitionNumber,
+                                        mInstallTaskProgress.totalPartitionNumber));
 
-                    int currentMax = max >> mInstallTaskProgress.partitionNumber;
-                    progress = max - currentMax * 2;
+                        // totalProgressPercentage is defined iff totalPartitionNumber is defined
+                        builder.setProgress(
+                                100,
+                                mInstallTaskProgress.totalProgressPercentage,
+                                /* indeterminate = */ false);
+                    } else {
+                        builder.setContentText(
+                                String.format(
+                                        "%s: %s partition",
+                                        msgInProgress, mInstallTaskProgress.partitionName));
 
-                    long currentProgress =
-                            (mInstallTaskProgress.installedSize >> 20)
-                                    * currentMax
-                                    / Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
+                        int max = 1024;
+                        int progress = 0;
 
-                    progress += (int) currentProgress;
+                        int currentMax = max >> mInstallTaskProgress.partitionNumber;
+                        progress = max - currentMax * 2;
 
-                    builder.setProgress(max, progress, false);
+                        long currentProgress =
+                                (mInstallTaskProgress.installedBytes >> 20)
+                                        * currentMax
+                                        / Math.max(mInstallTaskProgress.totalBytes >> 20, 1);
+
+                        progress += (int) currentProgress;
+
+                        builder.setProgress(max, progress, false);
+                    }
                 }
                 builder.addAction(new Notification.Action.Builder(
                         null, getString(R.string.notification_action_cancel),
@@ -609,10 +635,11 @@
         if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
             msg.append(
                     String.format(
-                            ", partition name: %s, progress: %d/%d",
+                            ", partition name: %s, progress: %d/%d, total_progress: %d%%",
                             mInstallTaskProgress.partitionName,
-                            mInstallTaskProgress.installedSize,
-                            mInstallTaskProgress.partitionSize));
+                            mInstallTaskProgress.installedBytes,
+                            mInstallTaskProgress.totalBytes,
+                            mInstallTaskProgress.totalProgressPercentage));
         }
         if (detail != null) {
             msg.append(", detail: " + detail);
@@ -639,7 +666,7 @@
         // TODO: send more info to the clients
         if (mInstallTaskProgress != null) {
             bundle.putLong(
-                    DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
+                    DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedBytes);
         }
 
         if (detail != null) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
index eae9de9..4073143 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
@@ -2,6 +2,6 @@
 
 option java_package com.android.dynsystem
 
-120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5)
+120000 dsu_progress_update (partition_name|3),(installed_bytes|2|5),(total_bytes|2|5),(partition_number|1|5),(total_partition_number|1|5),(total_progress_percentage|1|5)
 120001 dsu_install_complete
 120002 dsu_install_failed (cause|3)
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 998aeeab..2af7e00 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -113,22 +113,25 @@
 
     static class Progress {
         public final String partitionName;
-        public final long installedSize;
-        public final long partitionSize;
+        public final long installedBytes;
+        public final long totalBytes;
         public final int partitionNumber;
         public final int totalPartitionNumber;
+        public final int totalProgressPercentage;
 
         Progress(
                 String partitionName,
-                long installedSize,
-                long partitionSize,
+                long installedBytes,
+                long totalBytes,
                 int partitionNumber,
-                int totalPartitionNumber) {
+                int totalPartitionNumber,
+                int totalProgressPercentage) {
             this.partitionName = partitionName;
-            this.installedSize = installedSize;
-            this.partitionSize = partitionSize;
+            this.installedBytes = installedBytes;
+            this.totalBytes = totalBytes;
             this.partitionNumber = partitionNumber;
             this.totalPartitionNumber = totalPartitionNumber;
+            this.totalProgressPercentage = totalProgressPercentage;
         }
     }
 
@@ -149,20 +152,28 @@
     private final ProgressListener mListener;
     private final boolean mIsNetworkUrl;
     private final boolean mIsDeviceBootloaderUnlocked;
+    private final boolean mWantScratchPartition;
     private DynamicSystemManager.Session mInstallationSession;
     private KeyRevocationList mKeyRevocationList;
 
     private boolean mIsZip;
     private boolean mIsCompleted;
-
-    private String mPartitionName;
-    private long mPartitionSize;
-    private int mPartitionNumber;
-    private int mTotalPartitionNumber;
-
     private InputStream mStream;
     private ZipFile mZipFile;
 
+    private static final double PROGRESS_READONLY_PARTITION_WEIGHT = 0.8;
+    private static final double PROGRESS_WRITABLE_PARTITION_WEIGHT = 0.2;
+
+    private String mProgressPartitionName;
+    private long mProgressTotalBytes;
+    private int mProgressPartitionNumber;
+    private boolean mProgressPartitionIsReadonly;
+    private int mProgressCompletedReadonlyPartitions;
+    private int mProgressCompletedWritablePartitions;
+    private int mTotalReadonlyPartitions;
+    private int mTotalWritablePartitions;
+    private int mTotalPartitionNumber;
+
     InstallationAsyncTask(
             String url,
             String dsuSlot,
@@ -193,21 +204,18 @@
                 (pdbManager != null)
                         && (pdbManager.getFlashLockState()
                                 == PersistentDataBlockManager.FLASH_LOCK_UNLOCKED);
+        mWantScratchPartition = Build.IS_DEBUGGABLE;
     }
 
     @Override
     protected Throwable doInBackground(String... voids) {
         Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
 
-        final boolean wantScratchPartition = Build.IS_DEBUGGABLE;
         try {
             // call DynamicSystemManager to cleanup stuff
             mDynSystem.remove();
 
             verifyAndPrepare();
-            if (wantScratchPartition) {
-                ++mTotalPartitionNumber;
-            }
 
             mDynSystem.startInstallation(mDsuSlot);
 
@@ -226,7 +234,7 @@
                 return null;
             }
 
-            if (wantScratchPartition) {
+            if (mWantScratchPartition) {
                 // If host is debuggable, then install a scratch partition so that we can do
                 // adb remount in the guest system.
                 try {
@@ -290,14 +298,54 @@
     }
 
     @Override
-    protected void onProgressUpdate(Long... installedSize) {
+    protected void onProgressUpdate(Long... progress) {
+        final long installedBytes = progress[0];
+        int totalProgressPercentage = 0;
+        if (mTotalPartitionNumber > 0) {
+            final double readonlyPartitionWeight =
+                    mTotalReadonlyPartitions > 0
+                            ? PROGRESS_READONLY_PARTITION_WEIGHT / mTotalReadonlyPartitions
+                            : 0;
+            final double writablePartitionWeight =
+                    mTotalWritablePartitions > 0
+                            ? PROGRESS_WRITABLE_PARTITION_WEIGHT / mTotalWritablePartitions
+                            : 0;
+            double totalProgress = 0.0;
+            if (mProgressTotalBytes > 0) {
+                totalProgress +=
+                        (mProgressPartitionIsReadonly
+                                        ? readonlyPartitionWeight
+                                        : writablePartitionWeight)
+                                * installedBytes
+                                / mProgressTotalBytes;
+            }
+            totalProgress += readonlyPartitionWeight * mProgressCompletedReadonlyPartitions;
+            totalProgress += writablePartitionWeight * mProgressCompletedWritablePartitions;
+            totalProgressPercentage = (int) (totalProgress * 100);
+        }
         mListener.onProgressUpdate(
                 new Progress(
-                        mPartitionName,
-                        installedSize[0],
-                        mPartitionSize,
-                        mPartitionNumber,
-                        mTotalPartitionNumber));
+                        mProgressPartitionName,
+                        installedBytes,
+                        mProgressTotalBytes,
+                        mProgressPartitionNumber,
+                        mTotalPartitionNumber,
+                        totalProgressPercentage));
+    }
+
+    private void initPartitionProgress(String partitionName, long totalBytes, boolean readonly) {
+        if (mProgressPartitionNumber > 0) {
+            // Assume previous partition completed successfully.
+            if (mProgressPartitionIsReadonly) {
+                ++mProgressCompletedReadonlyPartitions;
+            } else {
+                ++mProgressCompletedWritablePartitions;
+            }
+        }
+        mProgressPartitionName = partitionName;
+        mProgressTotalBytes = totalBytes;
+        mProgressPartitionIsReadonly = readonly;
+        ++mProgressPartitionNumber;
     }
 
     private void verifyAndPrepare() throws Exception {
@@ -314,16 +362,12 @@
             throw new UnsupportedFormatException(
                 String.format(Locale.US, "Unsupported file format: %s", mUrl));
         }
-        // At least two partitions, {system, userdata}
-        mTotalPartitionNumber = 2;
 
         if (mIsNetworkUrl) {
             mStream = new URL(mUrl).openStream();
         } else if (URLUtil.isFileUrl(mUrl)) {
             if (mIsZip) {
                 mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
-                // {*.img in zip} + {userdata}
-                mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1;
             } else {
                 mStream = new URL(mUrl).openStream();
             }
@@ -334,6 +378,32 @@
                     String.format(Locale.US, "Unsupported URL: %s", mUrl));
         }
 
+        boolean hasTotalPartitionNumber = false;
+        if (mIsZip) {
+            if (mZipFile != null) {
+                // {*.img in zip} + {userdata}
+                hasTotalPartitionNumber = true;
+                mTotalReadonlyPartitions = calculateNumberOfImagesInLocalZip(mZipFile);
+                mTotalWritablePartitions = 1;
+            } else {
+                // TODO: Come up with a way to retrieve the number of total partitions from
+                // network URL.
+            }
+        } else {
+            // gzip has exactly two partitions, {system, userdata}
+            hasTotalPartitionNumber = true;
+            mTotalReadonlyPartitions = 1;
+            mTotalWritablePartitions = 1;
+        }
+
+        if (hasTotalPartitionNumber) {
+            if (mWantScratchPartition) {
+                // {scratch}
+                ++mTotalWritablePartitions;
+            }
+            mTotalPartitionNumber = mTotalReadonlyPartitions + mTotalWritablePartitions;
+        }
+
         try {
             String listUrl = mContext.getString(R.string.key_revocation_list_url);
             mKeyRevocationList = KeyRevocationList.fromUrl(new URL(listUrl));
@@ -370,9 +440,7 @@
             }
         };
 
-        mPartitionName = partitionName;
-        mPartitionSize = partitionSize;
-        ++mPartitionNumber;
+        initPartitionProgress(partitionName, partitionSize, /* readonly = */ false);
         publishProgress(/* installedSize = */ 0L);
 
         long prevInstalledSize = 0;
@@ -396,6 +464,10 @@
             }
         }
 
+        if (prevInstalledSize != partitionSize) {
+            publishProgress(partitionSize);
+        }
+
         if (mInstallationSession == null) {
             throw new IOException(
                     "Failed to start installation with requested size: " + partitionSize);
@@ -559,9 +631,7 @@
 
         mInstallationSession.setAshmem(pfd, memoryFile.length());
 
-        mPartitionName = partitionName;
-        mPartitionSize = partitionSize;
-        ++mPartitionNumber;
+        initPartitionProgress(partitionName, partitionSize, /* readonly = */ true);
         publishProgress(/* installedSize = */ 0L);
 
         long prevInstalledSize = 0;
@@ -588,6 +658,10 @@
             }
         }
 
+        if (prevInstalledSize != partitionSize) {
+            publishProgress(partitionSize);
+        }
+
         AvbPublicKey avbPublicKey = new AvbPublicKey();
         if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
             imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 8c70112..4183c08 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -157,6 +157,7 @@
 
     static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
     static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
+    static final String EXTRA_BUGREPORT_NONCE = "android.intent.extra.BUGREPORT_NONCE";
     static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
     static final String EXTRA_ID = "android.intent.extra.ID";
     static final String EXTRA_NAME = "android.intent.extra.NAME";
@@ -415,7 +416,7 @@
             final String bugreportFilePath = mInfo.bugreportFile.getAbsolutePath();
             if (mInfo.type == BugreportParams.BUGREPORT_MODE_REMOTE) {
                 sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath,
-                        mInfo.bugreportFile);
+                        mInfo.bugreportFile, mInfo.nonce);
             } else {
                 cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE, mBugreportsDir);
                 final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
@@ -428,7 +429,7 @@
     }
 
     private static void sendRemoteBugreportFinishedBroadcast(Context context,
-            String bugreportFileName, File bugreportFile) {
+            String bugreportFileName, File bugreportFile, long nonce) {
         cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE,
                 bugreportFile.getParentFile());
         final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
@@ -439,6 +440,7 @@
         }
         intent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE);
         intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
+        intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_NONCE, nonce);
         intent.putExtra(EXTRA_BUGREPORT, bugreportFileName);
         context.sendBroadcastAsUser(intent, UserHandle.SYSTEM,
                 android.Manifest.permission.DUMP);
@@ -613,11 +615,12 @@
         String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION);
         int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
                 BugreportParams.BUGREPORT_MODE_INTERACTIVE);
+        long nonce = intent.getLongExtra(EXTRA_BUGREPORT_NONCE, 0);
         String baseName = getBugreportBaseName(bugreportType);
         String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
 
         BugreportInfo info = new BugreportInfo(mContext, baseName, name,
-                shareTitle, shareDescription, bugreportType, mBugreportsDir);
+                shareTitle, shareDescription, bugreportType, mBugreportsDir, nonce);
         synchronized (mLock) {
             if (info.bugreportFile.exists()) {
                 Log.e(TAG, "Failed to start bugreport generation, the requested bugreport file "
@@ -1915,6 +1918,11 @@
          */
         final int type;
 
+        /**
+         * Nonce of the bugreport
+         */
+        final long nonce;
+
         private final Object mLock = new Object();
 
         /**
@@ -1922,12 +1930,13 @@
          */
         BugreportInfo(Context context, String baseName, String name,
                 @Nullable String shareTitle, @Nullable String shareDescription,
-                @BugreportParams.BugreportMode int type, File bugreportsDir) {
+                @BugreportParams.BugreportMode int type, File bugreportsDir, long nonce) {
             this.context = context;
             this.name = this.initialName = name;
             this.shareTitle = shareTitle == null ? "" : shareTitle;
             this.shareDescription = shareDescription == null ? "" : shareDescription;
             this.type = type;
+            this.nonce = nonce;
             this.baseName = baseName;
             this.bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
         }
@@ -2167,6 +2176,7 @@
             screenshotCounter = in.readInt();
             shareDescription = in.readString();
             type = in.readInt();
+            nonce = in.readLong();
         }
 
         @Override
@@ -2195,6 +2205,7 @@
             dest.writeInt(screenshotCounter);
             dest.writeString(shareDescription);
             dest.writeInt(type);
+            dest.writeLong(nonce);
         }
 
         @Override
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 8323e32..6c8a92d 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -72,6 +72,7 @@
 xuqiu@google.com
 zakcohen@google.com
 jernej@google.com
+jglazier@google.com
 
 #Android Auto
 hseog@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 52e8c31..9bfa37a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -210,7 +210,6 @@
     private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 13;
     private static final int NOTIFY_STARTED_WAKING_UP = 14;
     private static final int NOTIFY_SCREEN_TURNED_ON = 15;
-    private static final int NOTIFY_SCREEN_TURNED_OFF = 16;
     private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17;
     private static final int SYSTEM_READY = 18;
     private static final int CANCEL_KEYGUARD_EXIT_ANIM = 19;
@@ -441,7 +440,6 @@
     private boolean mInGestureNavigationMode;
 
     private boolean mWakeAndUnlocking;
-    private IKeyguardDrawnCallback mDrawnCallback;
     private CharSequence mCustomMessage;
 
     /**
@@ -1264,7 +1262,6 @@
     }
 
     public void onScreenTurnedOff() {
-        notifyScreenTurnedOff();
         mUpdateMonitor.dispatchScreenTurnedOff();
     }
 
@@ -1658,12 +1655,6 @@
         mHandler.sendMessage(msg);
     }
 
-    private void notifyScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "notifyScreenTurnedOff");
-        Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_TURNED_OFF);
-        mHandler.sendMessage(msg);
-    }
-
     /**
      * Send message to keyguard telling it to show itself
      * @see #handleShow
@@ -1848,9 +1839,6 @@
                     handleNotifyScreenTurnedOn();
                     Trace.endSection();
                     break;
-                case NOTIFY_SCREEN_TURNED_OFF:
-                    handleNotifyScreenTurnedOff();
-                    break;
                 case NOTIFY_STARTED_WAKING_UP:
                     Trace.beginSection(
                             "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP");
@@ -2231,16 +2219,6 @@
             IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner;
             mKeyguardExitAnimationRunner = null;
 
-            if (mWakeAndUnlocking && mDrawnCallback != null) {
-
-                // Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
-                // the next draw from here so we don't have to wait for window manager to signal
-                // this to our ViewRootImpl.
-                mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
-                notifyDrawn(mDrawnCallback);
-                mDrawnCallback = null;
-            }
-
             LatencyTracker.getInstance(mContext)
                     .onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
 
@@ -2596,11 +2574,7 @@
 
             mKeyguardViewControllerLazy.get().onScreenTurningOn();
             if (callback != null) {
-                if (mWakeAndUnlocking) {
-                    mDrawnCallback = callback;
-                } else {
-                    notifyDrawn(callback);
-                }
+                notifyDrawn(callback);
             }
         }
         Trace.endSection();
@@ -2615,13 +2589,6 @@
         Trace.endSection();
     }
 
-    private void handleNotifyScreenTurnedOff() {
-        synchronized (this) {
-            if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
-            mDrawnCallback = null;
-        }
-    }
-
     private void notifyDrawn(final IKeyguardDrawnCallback callback) {
         Trace.beginSection("KeyguardViewMediator#notifyDrawn");
         if (mPendingDrawnTasks.decrementAndGet() == 0) {
@@ -2790,7 +2757,6 @@
         pw.print("  mPendingLock: "); pw.println(mPendingLock);
         pw.print("  mPendingDrawnTasks: "); pw.println(mPendingDrawnTasks.get());
         pw.print("  mWakeAndUnlocking: "); pw.println(mWakeAndUnlocking);
-        pw.print("  mDrawnCallback: "); pw.println(mDrawnCallback);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index f6a1184..70f89e4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -835,7 +835,8 @@
                     uid,
                     interactedSubcardRank,
                     interactedSubcardCardinality,
-                    receivedLatencyMillis
+                    receivedLatencyMillis,
+                    null // Media cards cannot have subcards.
             )
             /* ktlint-disable max-line-length */
             if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 98b5dcc..2df56bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -405,7 +405,6 @@
         // During wake and unlock, we need to draw black before waking up to avoid abrupt
         // brightness changes due to display state transitions.
         boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
-        boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0;
         Runnable wakeUp = ()-> {
             if (!wasDeviceInteractive) {
                 if (DEBUG_BIO_WAKELOCK) {
@@ -414,15 +413,12 @@
                 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                         "android.policy:BIOMETRIC");
             }
-            if (delayWakeUp) {
-                mKeyguardViewMediator.onWakeAndUnlocking();
-            }
             Trace.beginSection("release wake-and-unlock");
             releaseBiometricWakeLock();
             Trace.endSection();
         };
 
-        if (!delayWakeUp && mMode != MODE_NONE) {
+        if (mMode != MODE_NONE) {
             wakeUp.run();
         }
         switch (mMode) {
@@ -472,11 +468,7 @@
                     mUpdateMonitor.awakenFromDream();
                 }
                 mNotificationShadeWindowController.setNotificationShadeFocusable(false);
-                if (delayWakeUp) {
-                    mHandler.postDelayed(wakeUp, mWakeUpDelay);
-                } else {
-                    mKeyguardViewMediator.onWakeAndUnlocking();
-                }
+                mKeyguardViewMediator.onWakeAndUnlocking();
                 Trace.endSection();
                 break;
             case MODE_ONLY_WAKE:
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 1095ba3..5fed6d3 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -129,14 +129,10 @@
                 DiskStatsFreeSpaceProto.FOLDER_METADATA);
 
         boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
-        boolean blockBased = fileBased ? false : StorageManager.isBlockEncrypted();
         if (protoFormat) {
             if (fileBased) {
                 proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
                         DiskStatsServiceDumpProto.ENCRYPTION_FILE_BASED);
-            } else if (blockBased) {
-                proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
-                        DiskStatsServiceDumpProto.ENCRYPTION_FULL_DISK);
             } else {
                 proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
                         DiskStatsServiceDumpProto.ENCRYPTION_NONE);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1a39ffa..73d9cc7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1528,7 +1528,7 @@
         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
             final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
             try {
-                cm.updateFirewallRule(chain, uid, isFirewallRuleAllow(chain, rule));
+                cm.setUidFirewallRule(chain, uid, rule);
             } catch (RuntimeException e) {
                 throw new IllegalStateException(e);
             }
@@ -1601,14 +1601,6 @@
         }
     }
 
-    // There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY.
-    private boolean isFirewallRuleAllow(int chain, int rule) {
-        if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
-            return getFirewallType(chain) == FIREWALL_DENYLIST;
-        }
-        return rule == INetd.FIREWALL_RULE_ALLOW;
-    }
-
     private void enforceSystemUid() {
         final int uid = mDeps.getCallingUid();
         if (uid != Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/SmartStorageMaintIdler.java b/services/core/java/com/android/server/SmartStorageMaintIdler.java
index 2dff72f..8996926 100644
--- a/services/core/java/com/android/server/SmartStorageMaintIdler.java
+++ b/services/core/java/com/android/server/SmartStorageMaintIdler.java
@@ -46,7 +46,7 @@
             }
             // ... and try again in a next period
             scheduleSmartIdlePass(SmartStorageMaintIdler.this,
-                StorageManagerService.SMART_IDLE_MAINT_PERIOD);
+                StorageManagerService.sSmartIdleMaintPeriod);
         }
     };
 
@@ -70,7 +70,7 @@
     /**
      * Schedule the smart storage idle maintenance job
      */
-    public static void scheduleSmartIdlePass(Context context, int nHours) {
+    public static void scheduleSmartIdlePass(Context context, int nMinutes) {
         StorageManagerService ms = StorageManagerService.sSelf;
         if ((ms == null) || ms.isPassedLifetimeThresh()) {
             return;
@@ -78,7 +78,7 @@
 
         JobScheduler tm = context.getSystemService(JobScheduler.class);
 
-        long nextScheduleTime = TimeUnit.HOURS.toMillis(nHours);
+        long nextScheduleTime = TimeUnit.MINUTES.toMillis(nMinutes);
 
         JobInfo.Builder builder = new JobInfo.Builder(SMART_MAINT_JOB_ID,
             SMART_STORAGE_MAINT_SERVICE);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 210613e..9e60cf6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -332,13 +332,15 @@
 
     @Nullable public static String sMediaStoreAuthorityProcessName;
 
-    // Run period in hour for smart idle maintenance
-    static final int SMART_IDLE_MAINT_PERIOD = 1;
+    // Smart idle maintenance running period in minute
+    static volatile int sSmartIdleMaintPeriod = 60;
 
     private final AtomicFile mSettingsFile;
-    private final AtomicFile mHourlyWriteFile;
+    private final AtomicFile mWriteRecordFile;
 
-    private static final int MAX_HOURLY_WRITE_RECORDS = 72;
+    // 72 hours (3 days)
+    private static final int MAX_PERIOD_WRITE_RECORD = 72 * 60;
+    private volatile int mMaxWriteRecords;
 
     /**
      * Default config values for smart idle maintenance
@@ -346,6 +348,10 @@
      */
     // Decide whether smart idle maintenance is enabled or not
     private static final boolean DEFAULT_SMART_IDLE_MAINT_ENABLED = false;
+    // Run period in minute for smart idle maintenance
+    private static final int DEFAULT_SMART_IDLE_MAINT_PERIOD = 60;
+    private static final int MIN_SMART_IDLE_MAINT_PERIOD = 10;
+    private static final int MAX_SMART_IDLE_MAINT_PERIOD = 24 * 60;
     // Storage lifetime percentage threshold to decide to turn off the feature
     private static final int DEFAULT_LIFETIME_PERCENT_THRESHOLD = 70;
     // Minimum required number of dirty + free segments to trigger GC
@@ -368,8 +374,8 @@
     private volatile boolean mNeedGC;
 
     private volatile boolean mPassedLifetimeThresh;
-    // Tracking storage hourly write amounts
-    private volatile int[] mStorageHourlyWrites;
+    // Tracking storage write amounts in one period
+    private volatile int[] mStorageWriteRecords;
 
     /**
      * <em>Never</em> hold the lock while performing downcalls into vold, since
@@ -914,7 +920,7 @@
 
     private void handleSystemReady() {
         if (prepareSmartIdleMaint()) {
-            SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, SMART_IDLE_MAINT_PERIOD);
+            SmartStorageMaintIdler.scheduleSmartIdlePass(mContext, sSmartIdleMaintPeriod);
         }
 
         // Start scheduling nominally-daily fstrim operations
@@ -1889,10 +1895,19 @@
 
         mSettingsFile = new AtomicFile(
                 new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
-        mHourlyWriteFile = new AtomicFile(
-                new File(Environment.getDataSystemDirectory(), "storage-hourly-writes"));
+        mWriteRecordFile = new AtomicFile(
+                new File(Environment.getDataSystemDirectory(), "storage-write-records"));
 
-        mStorageHourlyWrites = new int[MAX_HOURLY_WRITE_RECORDS];
+        sSmartIdleMaintPeriod = DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+            "smart_idle_maint_period", DEFAULT_SMART_IDLE_MAINT_PERIOD);
+        if (sSmartIdleMaintPeriod < MIN_SMART_IDLE_MAINT_PERIOD) {
+            sSmartIdleMaintPeriod = MIN_SMART_IDLE_MAINT_PERIOD;
+        } else if (sSmartIdleMaintPeriod > MAX_SMART_IDLE_MAINT_PERIOD) {
+            sSmartIdleMaintPeriod = MAX_SMART_IDLE_MAINT_PERIOD;
+        }
+
+        mMaxWriteRecords = MAX_PERIOD_WRITE_RECORD / sSmartIdleMaintPeriod;
+        mStorageWriteRecords = new int[mMaxWriteRecords];
 
         synchronized (mLock) {
             readSettingsLocked();
@@ -2638,7 +2653,7 @@
             // maintenance to avoid the conflict
             mNeedGC = false;
 
-            loadStorageHourlyWrites();
+            loadStorageWriteRecords();
             try {
                 mVold.refreshLatestWrite();
             } catch (Exception e) {
@@ -2654,13 +2669,17 @@
         return mPassedLifetimeThresh;
     }
 
-    private void loadStorageHourlyWrites() {
+    private void loadStorageWriteRecords() {
         FileInputStream fis = null;
 
         try {
-            fis = mHourlyWriteFile.openRead();
+            fis = mWriteRecordFile.openRead();
             ObjectInputStream ois = new ObjectInputStream(fis);
-            mStorageHourlyWrites = (int[])ois.readObject();
+
+            int periodValue = ois.readInt();
+            if (periodValue == sSmartIdleMaintPeriod) {
+                mStorageWriteRecords = (int[]) ois.readObject();
+            }
         } catch (FileNotFoundException e) {
             // Missing data is okay, probably first boot
         } catch (Exception e) {
@@ -2670,24 +2689,26 @@
         }
     }
 
-    private int getAverageHourlyWrite() {
-        return Arrays.stream(mStorageHourlyWrites).sum() / MAX_HOURLY_WRITE_RECORDS;
+    private int getAverageWriteAmount() {
+        return Arrays.stream(mStorageWriteRecords).sum() / mMaxWriteRecords;
     }
 
-    private void updateStorageHourlyWrites(int latestWrite) {
+    private void updateStorageWriteRecords(int latestWrite) {
         FileOutputStream fos = null;
 
-        System.arraycopy(mStorageHourlyWrites,0, mStorageHourlyWrites, 1,
-                     MAX_HOURLY_WRITE_RECORDS - 1);
-        mStorageHourlyWrites[0] = latestWrite;
+        System.arraycopy(mStorageWriteRecords, 0, mStorageWriteRecords, 1,
+                     mMaxWriteRecords - 1);
+        mStorageWriteRecords[0] = latestWrite;
         try {
-            fos = mHourlyWriteFile.startWrite();
+            fos = mWriteRecordFile.startWrite();
             ObjectOutputStream oos = new ObjectOutputStream(fos);
-            oos.writeObject(mStorageHourlyWrites);
-            mHourlyWriteFile.finishWrite(fos);
+
+            oos.writeInt(sSmartIdleMaintPeriod);
+            oos.writeObject(mStorageWriteRecords);
+            mWriteRecordFile.finishWrite(fos);
         } catch (IOException e) {
             if (fos != null) {
-                mHourlyWriteFile.failWrite(fos);
+                mWriteRecordFile.failWrite(fos);
             }
         }
     }
@@ -2751,22 +2772,23 @@
                     return;
                 }
 
-                int latestHourlyWrite = mVold.getWriteAmount();
-                if (latestHourlyWrite == -1) {
-                    Slog.w(TAG, "Failed to get storage hourly write");
+                int latestWrite = mVold.getWriteAmount();
+                if (latestWrite == -1) {
+                    Slog.w(TAG, "Failed to get storage write record");
                     return;
                 }
 
-                updateStorageHourlyWrites(latestHourlyWrite);
-                int avgHourlyWrite = getAverageHourlyWrite();
+                updateStorageWriteRecords(latestWrite);
+                int avgWriteAmount = getAverageWriteAmount();
 
-                Slog.i(TAG, "Set smart idle maintenance: " + "latest hourly write: " +
-                            latestHourlyWrite + ", average hourly write: " + avgHourlyWrite +
+                Slog.i(TAG, "Set smart idle maintenance: " + "latest write amount: " +
+                            latestWrite + ", average write amount: " + avgWriteAmount +
                             ", min segment threshold: " + mMinSegmentsThreshold +
                             ", dirty reclaim rate: " + mDirtyReclaimRate +
-                            ", segment reclaim weight:" + mSegmentReclaimWeight);
-                mVold.setGCUrgentPace(avgHourlyWrite, mMinSegmentsThreshold, mDirtyReclaimRate,
-                                      mSegmentReclaimWeight);
+                            ", segment reclaim weight: " + mSegmentReclaimWeight +
+                            ", period: " + sSmartIdleMaintPeriod);
+                mVold.setGCUrgentPace(avgWriteAmount, mMinSegmentsThreshold, mDirtyReclaimRate,
+                                      mSegmentReclaimWeight, sSmartIdleMaintPeriod);
             } else {
                 Slog.i(TAG, "Skipping smart idle maintenance - block based checkpoint in progress");
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dc393b6..c2c85e2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -544,6 +544,7 @@
     static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
     static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
+    static final String EXTRA_BUGREPORT_NONCE = "android.intent.extra.BUGREPORT_NONCE";
 
     /**
      * The maximum number of bytes that {@link #setProcessStateSummary} accepts.
@@ -6598,7 +6599,7 @@
      */
     @Override
     public void requestBugReport(@BugreportParams.BugreportMode int bugreportType) {
-        requestBugReportWithDescription(null, null, bugreportType);
+        requestBugReportWithDescription(null, null, bugreportType, 0L);
     }
 
     /**
@@ -6608,6 +6609,15 @@
     @Override
     public void requestBugReportWithDescription(@Nullable String shareTitle,
             @Nullable String shareDescription, int bugreportType) {
+        requestBugReportWithDescription(shareTitle, shareDescription, bugreportType, /*nonce*/ 0L);
+    }
+
+    /**
+     * Takes a bugreport using bug report API ({@code BugreportManager}) which gets
+     * triggered by sending a broadcast to Shell.
+     */
+    public void requestBugReportWithDescription(@Nullable String shareTitle,
+            @Nullable String shareDescription, int bugreportType, long nonce) {
         String type = null;
         switch (bugreportType) {
             case BugreportParams.BUGREPORT_MODE_FULL:
@@ -6658,6 +6668,7 @@
         triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
         triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
         triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
+        triggerShellBugreport.putExtra(EXTRA_BUGREPORT_NONCE, nonce);
         triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         if (shareTitle != null) {
@@ -6724,8 +6735,8 @@
      * Takes a bugreport remotely
      */
     @Override
-    public void requestRemoteBugReport() {
-        requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_REMOTE);
+    public void requestRemoteBugReport(long nonce) {
+        requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_REMOTE, nonce);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 651e98c..6e39a4c 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -73,8 +73,7 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
-        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler,
-                Context.RECEIVER_NOT_EXPORTED);
+        mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index de41611..a3c6f0a 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1102,6 +1102,7 @@
             mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
                     new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
             mDeviceBroker.postAccessoryPlugMediaUnmute(device);
+            setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
         }
 
         if (streamType == AudioSystem.STREAM_DEFAULT) {
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 092853f..89470ec 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -145,7 +145,7 @@
         filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
         filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
 
-        mContext.registerReceiver(this, filter, null, mHandler, Context.RECEIVER_NOT_EXPORTED);
+        mContext.registerReceiver(this, filter, null, mHandler);
         mSubscriptionManager.addOnSubscriptionsChangedListener(
                 executor, mSubscriptionChangedListener);
         mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 42c6dd43..b184d5c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4193,17 +4193,17 @@
      */
     @VisibleForTesting
     SurfaceControl computeImeParent() {
+        if (mImeLayeringTarget != null && mImeInputTarget != null
+                && mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) {
+            // Do not change parent if the window hasn't requested IME.
+            return null;
+        }
         // Attach it to app if the target is part of an app and such app is covering the entire
         // screen. If it's not covering the entire screen the IME might extend beyond the apps
         // bounds.
         if (shouldImeAttachedToApp()) {
-            if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) {
-                // Do not change parent if the window hasn't requested IME.
-                return null;
-            }
             return mImeLayeringTarget.mActivityRecord.getSurfaceControl();
         }
-
         // Otherwise, we just attach it to where the display area policy put it.
         return mImeWindowsContainer.getParent() != null
                 ? mImeWindowsContainer.getParent().getSurfaceControl() : null;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 10ae152..5124841 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -265,14 +265,12 @@
                 return state;
             }
         } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) {
-            // During switching tasks with gestural navigation, if the IME is attached to
-            // one app window on that time, even the next app window is behind the IME window,
-            // conceptually the window should not receive the IME insets if the next window is
-            // not eligible IME requester and ready to show IME on top of it.
-            final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp();
+            // During switching tasks with gestural navigation, before the next IME input target
+            // starts the input, we should adjust and freeze the last IME visibility of the window
+            // in case delivering obsoleted IME insets state during transitioning.
             final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME);
 
-            if (shouldImeAttachedToApp && originalImeSource != null) {
+            if (originalImeSource != null) {
                 final boolean imeVisibility =
                         w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME);
                 final InsetsState state = copyState ? new InsetsState(originalState)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
index d7cbd9b..346e859 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java
@@ -31,6 +31,7 @@
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -54,7 +55,9 @@
 import java.io.FileNotFoundException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.security.SecureRandom;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Class managing bugreport collection upon device owner's request.
@@ -78,6 +81,9 @@
     private final DevicePolicyManagerService mService;
     private final DevicePolicyManagerService.Injector mInjector;
 
+    private final SecureRandom mRng = new SecureRandom();
+
+    private final AtomicLong mRemoteBugreportNonce = new AtomicLong();
     private final AtomicBoolean mRemoteBugreportServiceIsActive = new AtomicBoolean();
     private final AtomicBoolean mRemoteBugreportSharingAccepted = new AtomicBoolean();
     private final Context mContext;
@@ -197,8 +203,13 @@
 
         final long callingIdentity = mInjector.binderClearCallingIdentity();
         try {
-            mInjector.getIActivityManager().requestRemoteBugReport();
+            long nonce;
+            do {
+                nonce = mRng.nextLong();
+            } while (nonce == 0);
+            mInjector.getIActivityManager().requestRemoteBugReport(nonce);
 
+            mRemoteBugreportNonce.set(nonce);
             mRemoteBugreportServiceIsActive.set(true);
             mRemoteBugreportSharingAccepted.set(false);
             registerRemoteBugreportReceivers();
@@ -231,6 +242,11 @@
     }
 
     private void onBugreportFinished(Intent intent) {
+        long nonce = intent.getLongExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_NONCE, 0);
+        if (nonce == 0 || mRemoteBugreportNonce.get() != nonce) {
+            Slogf.w(LOG_TAG, "Invalid nonce provided, ignoring " + nonce);
+            return;
+        }
         mHandler.removeCallbacks(mRemoteBugreportTimeoutRunnable);
         mRemoteBugreportServiceIsActive.set(false);
         final Uri bugreportUri = intent.getData();
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 66e840b..bbc28d7 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -54,7 +54,7 @@
 
     private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
 
-    private static final long BG_PROCESS_PERIOD = TimeUnit.DAYS.toMillis(1); // every 1 day.
+    private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours.
 
     private IProfCollectd mIProfcollect;
     private static ProfcollectForwardingService sSelfService;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index b770b3e..32cee44 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3065,11 +3065,11 @@
 
         // Simulate app re-start input or turning screen off/on then unlocked by un-secure
         // keyguard to back to the app, expect IME insets is not frozen
+        mDisplayContent.updateImeInputAndControlTarget(app);
+        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
         imeSource.setFrame(new Rect(100, 400, 500, 500));
         app.getInsetsState().addSource(imeSource);
         app.getInsetsState().setSourceVisible(ITYPE_IME, true);
-        mDisplayContent.updateImeInputAndControlTarget(app);
-        assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
 
         // Verify when IME is visible and the app can receive the right IME insets from policy.
         makeWindowVisibleAndDrawn(app, mImeWindow);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index f3c1ec5..9c0c213c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1075,6 +1075,21 @@
         assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent());
     }
 
+    @UseTestDisplay(addWindows = W_ACTIVITY)
+    @Test
+    public void testComputeImeParent_inputTargetNotUpdate() throws Exception {
+        WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1");
+        WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2");
+        doReturn(true).when(mDisplayContent).shouldImeAttachedToApp();
+        mDisplayContent.setImeLayeringTarget(app1);
+        mDisplayContent.setImeInputTarget(app1);
+        assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent());
+        mDisplayContent.setImeLayeringTarget(app2);
+        // Expect null means no change IME parent when the IME layering target not yet
+        // request IME to be the input target.
+        assertNull(mDisplayContent.computeImeParent());
+    }
+
     @Test
     public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception {
         final DisplayContent dc = createNewDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 7d50135..03b8188 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -931,6 +931,47 @@
 
     @UseTestDisplay(addWindows = { W_ACTIVITY })
     @Test
+    public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() {
+        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW,
+                ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2");
+        final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow");
+        spyOn(imeWindow);
+        doReturn(true).when(imeWindow).isVisible();
+        mDisplayContent.mInputMethodWindow = imeWindow;
+
+        final InsetsStateController controller = mDisplayContent.getInsetsStateController();
+        controller.getImeSourceProvider().setWindow(imeWindow, null, null);
+
+        // Simulate app2 in multi-window mode is going to background to switch to the fullscreen
+        // app which requests IME with updating all windows Insets State when IME is above app.
+        app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true;
+        mDisplayContent.setImeLayeringTarget(app);
+        mDisplayContent.setImeInputTarget(app);
+        assertTrue(mDisplayContent.shouldImeAttachedToApp());
+        controller.getImeSourceProvider().scheduleShowImePostLayout(app);
+        controller.getImeSourceProvider().getSource().setVisible(true);
+        controller.updateAboveInsetsState(imeWindow, false);
+
+        // Expect app windows behind IME can receive IME insets visible,
+        // but not for app2 in background.
+        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+
+        // Simulate app plays closing transition to app2.
+        // And app2 is now IME layering target but not yet to be the IME input target.
+        mDisplayContent.setImeLayeringTarget(app2);
+        app.mActivityRecord.commitVisibility(false, false);
+        assertTrue(app.mActivityRecord.mLastImeShown);
+        assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        // Verify the IME insets is still visible on app, but not for app2 during task switching.
+        assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible());
+        assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible());
+    }
+
+    @UseTestDisplay(addWindows = {W_ACTIVITY})
+    @Test
     public void testUpdateImeControlTargetWhenLeavingMultiWindow() {
         WindowState app = createWindow(null, TYPE_BASE_APPLICATION,
                 mAppWindow.mToken, "app");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index d7a5f0a..fd3b18a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -67,6 +67,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SharedMemory;
+import android.provider.DeviceConfig;
 import android.service.voice.HotwordDetectedResult;
 import android.service.voice.HotwordDetectionService;
 import android.service.voice.HotwordRejectedResult;
@@ -109,12 +110,20 @@
     private static final String TAG = "HotwordDetectionConnection";
     static final boolean DEBUG = false;
 
+    private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds";
     // TODO: These constants need to be refined.
     private static final long VALIDATION_TIMEOUT_MILLIS = 4000;
     private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000;
     private static final Duration MAX_UPDATE_TIMEOUT_DURATION =
             Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS);
     private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour
+    /**
+     * Time after which each HotwordDetectionService process is stopped and replaced by a new one.
+     * 0 indicates no restarts.
+     */
+    private static final int RESTART_PERIOD_SECONDS =
+            DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION,
+                    KEY_RESTART_PERIOD_IN_SECONDS, 3600); // 60 minutes by default
     private static final int MAX_ISOLATED_PROCESS_NUMBER = 10;
 
     // Hotword metrics
@@ -133,6 +142,7 @@
     // TODO: This may need to be a Handler(looper)
     private final ScheduledExecutorService mScheduledExecutorService =
             Executors.newSingleThreadScheduledExecutor();
+    @Nullable private final ScheduledFuture<?> mCancellationTaskFuture;
     private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false);
     private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied;
     private final @NonNull ServiceConnectionFactory mServiceConnectionFactory;
@@ -148,7 +158,6 @@
     private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback;
     private Instant mLastRestartInstant;
 
-    private ScheduledFuture<?> mCancellationTaskFuture;
     private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture;
     private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null;
 
@@ -194,16 +203,20 @@
         mLastRestartInstant = Instant.now();
         updateStateAfterProcessStart(options, sharedMemory);
 
-        // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
-        // until the current session is closed.
-        mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
-            Slog.v(TAG, "Time to restart the process, TTL has passed");
-            synchronized (mLock) {
-                restartProcessLocked();
-                HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
-                        HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
-            }
-        }, 30, 30, TimeUnit.MINUTES);
+        if (RESTART_PERIOD_SECONDS <= 0) {
+            mCancellationTaskFuture = null;
+        } else {
+            // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait
+            // until the current session is closed.
+            mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> {
+                Slog.v(TAG, "Time to restart the process, TTL has passed");
+                synchronized (mLock) {
+                    restartProcessLocked();
+                    HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType,
+                            HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE);
+                }
+            }, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS);
+        }
     }
 
     private void initAudioFlingerLocked() {
@@ -341,7 +354,9 @@
                 .setHotwordDetectionServiceProvider(null);
         mIdentity = null;
         updateServiceUidForAudioPolicy(Process.INVALID_UID);
-        mCancellationTaskFuture.cancel(/* may interrupt */ true);
+        if (mCancellationTaskFuture != null) {
+            mCancellationTaskFuture.cancel(/* may interrupt */ true);
+        }
         if (mAudioFlinger != null) {
             mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0);
         }
@@ -759,6 +774,7 @@
     }
 
     public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS);
         pw.print(prefix);
         pw.print("mBound=" + mRemoteHotwordDetectionService.isBound());
         pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger);
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index 7d857a2..184e154 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
 import android.os.Bundle;
@@ -261,6 +262,14 @@
     public static final String EXTRA_RESOLUTION_PORT_INDEX =
             "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
 
+    /**
+     * Intent extra set for resolution requests containing a bool indicating whether to use the
+     * given port index. For example, if {@link #switchToSubscription(int, PendingIntent)} is
+     * called, then no portIndex has been provided by the caller, and this extra will be false.
+     */
+    public static final String EXTRA_RESOLUTION_USE_PORT_INDEX =
+            "android.service.euicc.extra.RESOLUTION_USE_PORT_INDEX";
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "RESULT_" }, value = {
@@ -852,13 +861,19 @@
         }
         @Override
         public void switchToSubscription(int slotId, int portIndex, String iccid,
-                boolean forceDeactivateSim, ISwitchToSubscriptionCallback callback) {
+                boolean forceDeactivateSim, ISwitchToSubscriptionCallback callback,
+                boolean usePortIndex) {
             mExecutor.execute(new Runnable() {
                 @Override
                 public void run() {
-                    int result =
-                            EuiccService.this.onSwitchToSubscriptionWithPort(
-                                    slotId, portIndex, iccid, forceDeactivateSim);
+                    int result = 0;
+                    if (usePortIndex) {
+                        result = EuiccService.this.onSwitchToSubscriptionWithPort(
+                                slotId, portIndex, iccid, forceDeactivateSim);
+                    } else {
+                        result = EuiccService.this.onSwitchToSubscription(
+                                slotId, iccid, forceDeactivateSim);
+                    }
                     try {
                         callback.onComplete(result);
                     } catch (RemoteException e) {
diff --git a/telephony/java/android/service/euicc/IEuiccService.aidl b/telephony/java/android/service/euicc/IEuiccService.aidl
index aa30c9e..030e11a 100644
--- a/telephony/java/android/service/euicc/IEuiccService.aidl
+++ b/telephony/java/android/service/euicc/IEuiccService.aidl
@@ -49,7 +49,7 @@
     void getEuiccInfo(int slotId, in IGetEuiccInfoCallback callback);
     void deleteSubscription(int slotId, String iccid, in IDeleteSubscriptionCallback callback);
     void switchToSubscription(int slotId, int portIndex, String iccid, boolean forceDeactivateSim,
-            in ISwitchToSubscriptionCallback callback);
+            in ISwitchToSubscriptionCallback callback, boolean useLegacyApi);
     void updateSubscriptionNickname(int slotId, String iccid, String nickname,
             in IUpdateSubscriptionNicknameCallback callback);
     void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 4b8b590..974392e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -941,6 +941,13 @@
     public static final String PROFILE_CLASS = SimInfo.COLUMN_PROFILE_CLASS;
 
     /**
+     * TelephonyProvider column name for the port index of the active UICC port.
+     * <P>Type: INTEGER (int)</P>
+     * @hide
+     */
+    public static final String PORT_INDEX = SimInfo.COLUMN_PORT_INDEX;
+
+    /**
      * TelephonyProvider column name for VoIMS opt-in status.
      *
      * <P>Type: INTEGER (int)</P>
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index cdba635..a5adf52 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -327,6 +327,9 @@
      */
     public static final int DEFAULT_PORT_INDEX = 0;
 
+    /** @hide */
+    public static final int INVALID_PORT_INDEX = -1;
+
     private final Context mContext;
     private final int mSubId;
     @UnsupportedAppUsage
@@ -16426,32 +16429,6 @@
     }
 
     /**
-     * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
-     *
-     * @hide
-     * @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon
-     * prior to API finalization.
-     */
-    @Deprecated
-    @SystemApi
-    public interface CarrierPrivilegesListener {
-        /**
-         * Called when the set of packages with carrier privileges has changed.
-         *
-         * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
-         * switch and the same set of packages remains privileged after the switch.
-         *
-         * <p>At registration, the callback will receive the current set of privileged packages.
-         *
-         * @param privilegedPackageNames The updated set of package names that have carrier
-         *     privileges
-         * @param privilegedUids The updated set of UIDs that have carrier privileges
-         */
-        void onCarrierPrivilegesChanged(
-                @NonNull List<String> privilegedPackageNames, @NonNull int[] privilegedUids);
-    }
-
-    /**
      * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
      *
      * <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
@@ -16500,61 +16477,6 @@
     }
 
     /**
-     * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
-     * receive callbacks when the set of packages with carrier privileges changes. The callback will
-     * immediately be called with the latest state.
-     *
-     * @param logicalSlotIndex The SIM slot to listen on
-     * @param executor The executor where {@code listener} will be invoked
-     * @param listener The callback to register
-     * @hide
-     * @deprecated Use {@link #registerCarrierPrivilegesCallback} instead. This API will be
-     * removed prior to API finalization.
-     */
-    @Deprecated
-    @SystemApi
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void addCarrierPrivilegesListener(
-            int logicalSlotIndex,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull CarrierPrivilegesListener listener) {
-        if (mContext == null) {
-            throw new IllegalStateException("Telephony service is null");
-        } else if (executor == null || listener == null) {
-            throw new IllegalArgumentException(
-                    "CarrierPrivilegesListener and executor must be non-null");
-        }
-        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
-        if (mTelephonyRegistryMgr == null) {
-            throw new IllegalStateException("Telephony registry service is null");
-        }
-        mTelephonyRegistryMgr.addCarrierPrivilegesListener(logicalSlotIndex, executor, listener);
-    }
-
-    /**
-     * Unregisters an existing {@link CarrierPrivilegesListener}.
-     *
-     * @hide
-     * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
-     * removed prior to API finalization.
-     */
-    @Deprecated
-    @SystemApi
-    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
-        if (mContext == null) {
-            throw new IllegalStateException("Telephony service is null");
-        } else if (listener == null) {
-            throw new IllegalArgumentException("CarrierPrivilegesListener must be non-null");
-        }
-        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
-        if (mTelephonyRegistryMgr == null) {
-            throw new IllegalStateException("Telephony registry service is null");
-        }
-        mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
-    }
-
-    /**
      * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
      * receive callbacks when the set of packages with carrier privileges changes. The callback will
      * immediately be called with the latest state.
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index aa514b9..a1e4f29 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -16,7 +16,6 @@
 package android.telephony.euicc;
 
 import android.Manifest;
-import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -29,7 +28,6 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.telephony.TelephonyFrameworkInitializer;
@@ -37,13 +35,11 @@
 import android.telephony.euicc.EuiccCardManager.ResetOption;
 
 import com.android.internal.telephony.euicc.IEuiccController;
-import com.android.internal.telephony.euicc.IResultCallback;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
 /**
@@ -219,20 +215,6 @@
             "android.telephony.euicc.action.START_EUICC_ACTIVATION";
 
     /**
-     * Result codes passed to the ResultListener by
-     * {@link #switchToSubscription(int, int, Executor, ResultListener)}
-     *
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"EMBEDDED_SUBSCRIPTION_RESULT_"}, value = {
-            EMBEDDED_SUBSCRIPTION_RESULT_OK,
-            EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
-            EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
-    })
-    public @interface ResultCode{}
-
-    /**
      * Result code for an operation indicating that the operation succeeded.
      */
     public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
@@ -821,6 +803,13 @@
      */
     public static final int ERROR_OPERATION_BUSY = 10016;
 
+    /**
+     * Failure due to target port is not supported.
+     * @see #switchToSubscription(int, int, PendingIntent)
+     */
+    public static final int ERROR_INVALID_PORT = 10017;
+
+
     private final Context mContext;
     private int mCardId;
 
@@ -1136,6 +1125,15 @@
      * intent to prompt the user to accept the download. The caller should also be authorized to
      * manage the subscription to be enabled.
      *
+     * <p> From Android T, devices might support MEP(Multiple Enabled Profile), the subscription
+     * can be installed on different port from the eUICC. Calling apps with carrier privilege
+     * (see {@link TelephonyManager#hasCarrierPrivileges}) over the currently active subscriptions
+     * can use {@link #switchToSubscription(int, int, PendingIntent)} to specify which port to
+     * enable the subscription. Otherwise, use this API to enable the subscription on the eUICC
+     * and the platform will internally resolve a port. If there is no available port,
+     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} might be returned in the callback
+     * intent to prompt the user to disable an already-active subscription.
+     *
      * @param subscriptionId the ID of the subscription to enable. May be
      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
      *     current profile without activating another profile to replace it. If it's a disable
@@ -1143,12 +1141,7 @@
      *     permission, or the calling app must be authorized to manage the active subscription on
      *     the target eUICC.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
-     *
-     * @deprecated From T, callers should use
-     * {@link #switchToSubscription(int, int, Executor, ResultListener)} instead to specify a port
-     * index on the card to switch to.
      */
-    @Deprecated
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
         if (!isEnabled()) {
@@ -1166,20 +1159,19 @@
     /**
      * Switch to (enable) the given subscription.
      *
-     * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
-     * or the calling app must be authorized to manage both the currently-active subscription and
-     * the subscription to be enabled according to the subscription metadata. Without the former,
-     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
-     * intent to prompt the user to accept the download.
+     * <p> Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
+     * or the caller must be having both the carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}) over any currently active subscriptions
+     * and the subscription to be enabled according to the subscription metadata.
+     * Without the former permissions, an SecurityException is thrown.
      *
-     * <p>On a multi-active SIM device, requires the
-     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
-     * only if the targeted eUICC does not currently have an active subscription or the calling app
-     * is authorized to manage the active subscription on the target eUICC, and the calling app is
-     * authorized to manage any active subscription on any SIM. Without it, an
-     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
-     * intent to prompt the user to accept the download. The caller should also be authorized to
-     * manage the subscription to be enabled.
+     * <p> If the caller is passing invalid port index,
+     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_ERROR} with detailed error code
+     * {@link #ERROR_INVALID_PORT} will be returned.
+     *
+     * <p> Depending on the target port and permission check,
+     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} might be returned to the callback
+     * intent to prompt the user to authorize before the switch.
      *
      * @param subscriptionId the ID of the subscription to enable. May be
      *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
@@ -1188,47 +1180,24 @@
      *     permission, or the calling app must be authorized to manage the active subscription on
      *     the target eUICC.
      * @param portIndex the index of the port to target for the enabled subscription
-     * @param executor an Executor on which to run the callback
-     * @param callback a {@link ResultListener} which will run when the operation completes
+     * @param callbackIntent a PendingIntent to launch when the operation completes.
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void switchToSubscription(int subscriptionId, int portIndex,
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull ResultListener callback) {
+            @NonNull PendingIntent callbackIntent) {
         if (!isEnabled()) {
-            sendUnavailableErrorToCallback(executor, callback);
+            sendUnavailableError(callbackIntent);
             return;
         }
         try {
-            IResultCallback internalCallback = new IResultCallback.Stub() {
-                @Override
-                public void onComplete(int result, Intent resultIntent) {
-                    executor.execute(() -> Binder.withCleanCallingIdentity(
-                            () -> callback.onComplete(result, resultIntent)));
-                }
-            };
-            getIEuiccController().switchToSubscriptionWithPort(mCardId, portIndex,
-                    subscriptionId, mContext.getOpPackageName(), internalCallback);
+            getIEuiccController().switchToSubscriptionWithPort(mCardId,
+                    subscriptionId, portIndex, mContext.getOpPackageName(), callbackIntent);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Callback to receive the result of an EuiccManager API.
-     */
-    public interface ResultListener {
-        /**
-         * Called on completion of some operation.
-         * @param resultCode representing success or specific failure of the operation
-         *                   (See {@link ResultCode})
-         * @param resultIntent an intent used to start a resolution activity when an error
-         *                     occurs that can be resolved by the user
-         */
-        void onComplete(@ResultCode int resultCode, @Nullable Intent resultIntent);
-    }
-
-    /**
      * Update the nickname for the given subscription.
      *
      * <p>Requires that the calling app has carrier privileges according to the metadata of the
@@ -1499,13 +1468,6 @@
         }
     }
 
-    private static void sendUnavailableErrorToCallback(@NonNull Executor executor,
-            ResultListener callback) {
-        Integer result = EMBEDDED_SUBSCRIPTION_RESULT_ERROR;
-        executor.execute(() ->
-                Binder.withCleanCallingIdentity(() -> callback.onComplete(result, null)));
-    }
-
     private static IEuiccController getIEuiccController() {
         return IEuiccController.Stub.asInterface(
                 TelephonyFrameworkInitializer
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 7f5982f..dda95b1 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -22,8 +22,6 @@
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
 
-import com.android.internal.telephony.euicc.IResultCallback;
-
 import java.util.List;
 
 /** @hide */
@@ -45,8 +43,8 @@
         in PendingIntent callbackIntent);
     oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage,
         in PendingIntent callbackIntent);
-    oneway void switchToSubscriptionWithPort(int cardId, int portIndex, int subscriptionId,
-        String callingPackage, in IResultCallback callback);
+    oneway void switchToSubscriptionWithPort(int cardId, int subscriptionId, int portIndex,
+        String callingPackage, in PendingIntent callbackIntent);
     oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
         String callingPackage, in PendingIntent callbackIntent);
     oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
diff --git a/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl b/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
deleted file mode 100644
index 69f479c..0000000
--- a/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.telephony.euicc;
-
-import android.content.Intent;
-
-/** @hide */
-oneway interface IResultCallback {
-    void onComplete(int resultCode, in Intent resultIntent);
-}
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index b673957..5f606e1 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -174,7 +174,7 @@
 
     private IntentFilter getIntentFilter() {
         final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
+        verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
 
         return captor.getValue();
     }
@@ -258,8 +258,7 @@
                         eq(mTelephonySubscriptionTracker),
                         any(IntentFilter.class),
                         any(),
-                        eq(mHandler),
-                        eq(Context.RECEIVER_NOT_EXPORTED));
+                        eq(mHandler));
         final IntentFilter filter = getIntentFilter();
         assertEquals(2, filter.countActions());
         assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
