Merge "Update dream blur and fade to match the bouncer scrim" into tm-dev
diff --git a/Android.bp b/Android.bp
index 149b223..cd110de 100644
--- a/Android.bp
+++ b/Android.bp
@@ -272,8 +272,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/Bluetooth/framework/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
             "packages/modules/Media/apex/aidl/stable",
@@ -531,8 +529,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/Bluetooth/framework/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
             "packages/modules/Media/apex/aidl/stable",
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 528be3c..a09f39f 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -348,7 +348,8 @@
             new SparseArray<>();
 
     private AppStateTrackerImpl mAppStateTracker;
-    private boolean mAppStandbyParole;
+    @VisibleForTesting
+    boolean mAppStandbyParole;
 
     /**
      * A container to keep rolling window history of previous times when an alarm was sent to
@@ -1891,6 +1892,9 @@
                         (AppStateTrackerImpl) LocalServices.getService(AppStateTracker.class);
                 mAppStateTracker.addListener(mForceAppStandbyListener);
 
+                final BatteryManager bm = getContext().getSystemService(BatteryManager.class);
+                mAppStandbyParole = bm.isCharging();
+
                 mClockReceiver.scheduleTimeTickEvent();
                 mClockReceiver.scheduleDateChangedEvent();
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java b/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
index f91472b..daf1ee1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/PendingJobQueue.java
@@ -182,8 +182,10 @@
         if (earliestQueue != null) {
             final JobStatus job = earliestQueue.next();
             // Change the front of the queue if we've pulled pullLimit jobs from the current head
+            // or we're dealing with test jobs
             // or the current head has no more jobs to provide.
             if (++mPullCount >= pullLimit
+                    || (job != null && earliestQueue.peekNextOverrideState() != job.overrideState)
                     || earliestQueue.peekNextTimestamp() == AppJobQueue.NO_NEXT_TIMESTAMP) {
                 mOrderedQueues.poll();
                 if (earliestQueue.peekNextTimestamp() != AppJobQueue.NO_NEXT_TIMESTAMP) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/ChargingModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/ChargingModifier.java
index 712e13e..2b48d49 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/ChargingModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/ChargingModifier.java
@@ -76,6 +76,8 @@
     }
 
     private final class ChargingTracker extends BroadcastReceiver {
+        private boolean mIsSetup = false;
+
         /**
          * Track whether we're "charging", where charging means that we're ready to commit to
          * doing work.
@@ -83,6 +85,10 @@
         private volatile boolean mCharging;
 
         public void startTracking(@NonNull Context context) {
+            if (mIsSetup) {
+                return;
+            }
+
             final IntentFilter filter = new IntentFilter();
             filter.addAction(BatteryManager.ACTION_CHARGING);
             filter.addAction(BatteryManager.ACTION_DISCHARGING);
@@ -91,10 +97,17 @@
             // Initialise tracker state.
             final BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
             mCharging = batteryManager.isCharging();
+
+            mIsSetup = true;
         }
 
         public void stopTracking(@NonNull Context context) {
+            if (!mIsSetup) {
+                return;
+            }
+
             context.unregisterReceiver(this);
+            mIsSetup = false;
         }
 
         @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/DeviceIdleModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/DeviceIdleModifier.java
index 8a64238..47ff307 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/DeviceIdleModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/DeviceIdleModifier.java
@@ -72,6 +72,7 @@
     }
 
     private final class DeviceIdleTracker extends BroadcastReceiver {
+        private boolean mIsSetup = false;
 
         private volatile boolean mDeviceIdle;
         private volatile boolean mDeviceLightIdle;
@@ -80,6 +81,10 @@
         }
 
         void startTracking(@NonNull Context context) {
+            if (mIsSetup) {
+                return;
+            }
+
             IntentFilter filter = new IntentFilter();
             filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
             filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
@@ -88,10 +93,17 @@
             // Initialise tracker state.
             mDeviceIdle = mPowerManager.isDeviceIdleMode();
             mDeviceLightIdle = mPowerManager.isLightDeviceIdleMode();
+
+            mIsSetup = true;
         }
 
         void stopTracking(@NonNull Context context) {
+            if (!mIsSetup) {
+                return;
+            }
+
             context.unregisterReceiver(this);
+            mIsSetup = false;
         }
 
         @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/PowerSaveModeModifier.java b/apex/jobscheduler/service/java/com/android/server/tare/PowerSaveModeModifier.java
index 4aaa9f4..542bfd1 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/PowerSaveModeModifier.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/PowerSaveModeModifier.java
@@ -72,6 +72,8 @@
 
     // TODO: migrate to relying on PowerSaveState and ServiceType.TARE
     private final class PowerSaveModeTracker extends BroadcastReceiver {
+        private boolean mIsSetup = false;
+
         private final PowerManager mPowerManager;
         private volatile boolean mPowerSaveModeEnabled;
 
@@ -80,16 +82,27 @@
         }
 
         public void startTracking(@NonNull Context context) {
+            if (mIsSetup) {
+                return;
+            }
+
             final IntentFilter filter = new IntentFilter();
             filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
             context.registerReceiver(this, filter);
 
             // Initialise tracker state.
             mPowerSaveModeEnabled = mPowerManager.isPowerSaveMode();
+
+            mIsSetup = true;
         }
 
         public void stopTracking(@NonNull Context context) {
+            if (!mIsSetup) {
+                return;
+            }
+
             context.unregisterReceiver(this);
+            mIsSetup = false;
         }
 
         @Override
diff --git a/core/api/current.txt b/core/api/current.txt
index 317d46e..d03ab96 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -851,7 +851,6 @@
     field public static final int indicatorRight = 16843022; // 0x101010e
     field public static final int indicatorStart = 16843729; // 0x10103d1
     field public static final int inflatedId = 16842995; // 0x10100f3
-    field public static final int inheritKeyStoreKeys;
     field public static final int inheritShowWhenLocked = 16844188; // 0x101059c
     field public static final int initOrder = 16842778; // 0x101001a
     field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
@@ -10438,13 +10437,11 @@
     field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
     field public static final String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
-    field public static final String EXTRA_NEW_UID = "android.intent.extra.NEW_UID";
     field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
     field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
     field public static final String EXTRA_PERMISSION_GROUP_NAME = "android.intent.extra.PERMISSION_GROUP_NAME";
     field public static final String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
-    field public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";
     field public static final String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
     field public static final String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
     field public static final String EXTRA_QUICK_VIEW_FEATURES = "android.intent.extra.QUICK_VIEW_FEATURES";
@@ -10476,7 +10473,6 @@
     field public static final String EXTRA_TIMEZONE = "time-zone";
     field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
     field public static final String EXTRA_UID = "android.intent.extra.UID";
-    field public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";
     field public static final String EXTRA_USER = "android.intent.extra.USER";
     field public static final String EXTRA_USER_INITIATED = "android.intent.extra.USER_INITIATED";
     field public static final int FILL_IN_ACTION = 1; // 0x1
@@ -12332,6 +12328,7 @@
     method @Nullable public java.util.Set<java.lang.String> getCategories();
     method @Nullable public CharSequence getDisabledMessage();
     method public int getDisabledReason();
+    method public int getExcludedFromSurfaces();
     method @Nullable public android.os.PersistableBundle getExtras();
     method @NonNull public String getId();
     method @Nullable public android.content.Intent getIntent();
@@ -12348,8 +12345,8 @@
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
+    method public boolean isExcludedFromSurfaces(int);
     method public boolean isImmutable();
-    method public boolean isIncludedIn(int);
     method public boolean isPinned();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e5e13a8..d6949bf 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2636,18 +2636,18 @@
     method public int describeContents();
     method @NonNull public float[] getAnchorPointInOutputUvSpace();
     method @NonNull public float[] getAnchorPointInWorldSpace();
-    method public float getCameraOrbitPitchDegrees();
-    method public float getCameraOrbitYawDegrees();
+    method @FloatRange(from=-90.0F, to=90.0f) public float getCameraOrbitPitchDegrees();
+    method @FloatRange(from=-180.0F, to=180.0f) public float getCameraOrbitYawDegrees();
     method public float getDollyDistanceInWorldSpace();
-    method public float getFrustumFarInWorldSpace();
-    method public float getFrustumNearInWorldSpace();
-    method public float getVerticalFovDegrees();
+    method @FloatRange(from=0.0f) public float getFrustumFarInWorldSpace();
+    method @FloatRange(from=0.0f) public float getFrustumNearInWorldSpace();
+    method @FloatRange(from=0.0f, to=180.0f, fromInclusive=false) public float getVerticalFovDegrees();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.wallpapereffectsgeneration.CameraAttributes> CREATOR;
   }
 
   public static final class CameraAttributes.Builder {
-    ctor public CameraAttributes.Builder(@NonNull float[], @NonNull float[]);
+    ctor public CameraAttributes.Builder(@NonNull @Size(3) float[], @NonNull @Size(2) float[]);
     method @NonNull public android.app.wallpapereffectsgeneration.CameraAttributes build();
     method @NonNull public android.app.wallpapereffectsgeneration.CameraAttributes.Builder setCameraOrbitPitchDegrees(@FloatRange(from=-90.0F, to=90.0f) float);
     method @NonNull public android.app.wallpapereffectsgeneration.CameraAttributes.Builder setCameraOrbitYawDegrees(@FloatRange(from=-180.0F, to=180.0f) float);
@@ -2675,12 +2675,11 @@
     method @NonNull public String getTaskId();
     method @NonNull public java.util.List<android.app.wallpapereffectsgeneration.TexturedMesh> getTexturedMeshes();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int CINEMATIC_EFFECT_STATUS_ERROR = 2; // 0x2
-    field public static final int CINEMATIC_EFFECT_STATUS_NOT_READY = 3; // 0x3
+    field public static final int CINEMATIC_EFFECT_STATUS_ERROR = 0; // 0x0
+    field public static final int CINEMATIC_EFFECT_STATUS_NOT_READY = 2; // 0x2
     field public static final int CINEMATIC_EFFECT_STATUS_OK = 1; // 0x1
-    field public static final int CINEMATIC_EFFECT_STATUS_PENDING = 4; // 0x4
-    field public static final int CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS = 5; // 0x5
-    field public static final int CINEMATIC_EFFECT_STATUS_UNKNOWN = 0; // 0x0
+    field public static final int CINEMATIC_EFFECT_STATUS_PENDING = 3; // 0x3
+    field public static final int CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS = 4; // 0x4
     field @NonNull public static final android.os.Parcelable.Creator<android.app.wallpapereffectsgeneration.CinematicEffectResponse> CREATOR;
     field public static final int IMAGE_CONTENT_TYPE_LANDSCAPE = 2; // 0x2
     field public static final int IMAGE_CONTENT_TYPE_OTHER = 3; // 0x3
@@ -11816,10 +11815,10 @@
 package android.service.trust {
 
   public final class GrantTrustResult implements android.os.Parcelable {
+    ctor public GrantTrustResult(int);
     method public int describeContents();
     method public int getStatus();
     method @NonNull public static String statusToString(int);
-    method @NonNull public static android.service.trust.GrantTrustResult withStatus(int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.trust.GrantTrustResult> CREATOR;
     field public static final int STATUS_UNKNOWN = 0; // 0x0
@@ -12041,8 +12040,9 @@
   public abstract class WallpaperEffectsGenerationService extends android.app.Service {
     ctor public WallpaperEffectsGenerationService();
     method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public abstract void onGenerateCinematicEffect(@NonNull android.app.wallpapereffectsgeneration.CinematicEffectRequest);
+    method @MainThread public abstract void onGenerateCinematicEffect(@NonNull android.app.wallpapereffectsgeneration.CinematicEffectRequest);
     method public final void returnCinematicEffectResponse(@NonNull android.app.wallpapereffectsgeneration.CinematicEffectResponse);
+    field public static final String SERVICE_INTERFACE = "android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService";
   }
 
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a28b3e9..5eda587 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5707,7 +5707,6 @@
      * their launch had come from the original activity.
      * @param intent The Intent to start.
      * @param options ActivityOptions or null.
-     * @param permissionToken Token received from the system that permits this call to be made.
      * @param ignoreTargetSecurity If true, the activity manager will not check whether the
      * caller it is doing the start is, is actually allowed to start the target activity.
      * If you set this to true, you must set an explicit component in the Intent and do any
@@ -5716,18 +5715,18 @@
      * @hide
      */
     public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
-            IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
-        startActivityAsCaller(intent, options, permissionToken, ignoreTargetSecurity, userId, -1);
+            boolean ignoreTargetSecurity, int userId) {
+        startActivityAsCaller(intent, options, ignoreTargetSecurity, userId, -1);
     }
 
     /**
-     * @see #startActivityAsCaller(Intent, Bundle, IBinder, boolean, int)
+     * @see #startActivityAsCaller(Intent, Bundle, boolean, int)
      * @param requestCode The request code used for returning a result or -1 if no result should be
      *                    returned.
      * @hide
      */
     public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
-            IBinder permissionToken, boolean ignoreTargetSecurity, int userId, int requestCode) {
+            boolean ignoreTargetSecurity, int userId, int requestCode) {
         if (mParent != null) {
             throw new RuntimeException("Can't be called from a child");
         }
@@ -5735,8 +5734,7 @@
         Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivityAsCaller(
                         this, mMainThread.getApplicationThread(), mToken, this,
-                        intent, requestCode, options, permissionToken, ignoreTargetSecurity,
-                        userId);
+                        intent, requestCode, options, ignoreTargetSecurity, userId);
         if (ar != null) {
             mMainThread.sendActivityResult(
                     mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData());
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index a836625..6fc0c26 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -106,14 +106,6 @@
             RESIZE_MODE_PRESERVE_WINDOW | RESIZE_MODE_FORCED;
 
     /**
-     * Extra included on intents that are delegating the call to
-     * ActivityManager#startActivityAsCaller to another app.  This token is necessary for that call
-     * to succeed.  Type is IBinder.
-     * @hide
-     */
-    public static final String EXTRA_PERMISSION_TOKEN = "android.app.extra.PERMISSION_TOKEN";
-
-    /**
      * Extra included on intents that contain an EXTRA_INTENT, with options that the contained
      * intent may want to be started with.  Type is Bundle.
      * TODO: remove once the ChooserActivity moves to systemui
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index ef9a2f2..87b2417 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -141,7 +141,7 @@
     int startActivityAsCaller(in IApplicationThread caller, in String callingPackage,
             in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
             int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options,
-            IBinder permissionToken, boolean ignoreTargetSecurity, int userId);
+            boolean ignoreTargetSecurity, int userId);
 
     boolean isActivityStartAllowedOnDisplay(int displayId, in Intent intent, in String resolvedType,
             int userId);
@@ -182,18 +182,6 @@
     int addAppTask(in IBinder activityToken, in Intent intent,
             in ActivityManager.TaskDescription description, in Bitmap thumbnail);
     Point getAppTaskThumbnailSize();
-    /**
-     * Only callable from the system. This token grants a temporary permission to call
-     * #startActivityAsCaller. The token will time out after START_AS_CALLER_TOKEN_TIMEOUT
-     * if it is not used.
-     *
-     * @param componentName The component name of the delegated component that is allowed to
-     *                      call #startActivityAsCaller with the returned token.
-     *
-     * @return Returns a token that can be given to a "delegate" app that may call
-     *         #startActivityAsCaller
-     */
-    IBinder requestStartActivityPermissionToken(in ComponentName componentName);
 
     oneway void releaseSomeActivities(in IApplicationThread app);
     Bitmap getTaskDescriptionIcon(in String filename, int userId);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ac979c4..995a9f3 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -381,6 +381,10 @@
      * Force the global system in or out of touch mode. This can be used if your
      * instrumentation relies on the UI being in one more or the other when it starts.
      *
+     * <p><b>Note:</b> Starting from Android {@link Build.VERSION_CODES#TIRAMISU}, this method
+     * will only take effect if the instrumentation was sourced from a process with
+     * {@code MODIFY_TOUCH_MODE_STATE} internal permission granted (shell already have it).
+     *
      * @param inTouch Set to true to be in touch mode, false to be in focus mode.
      */
     public void setInTouchMode(boolean inTouch) {
@@ -1995,7 +1999,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public ActivityResult execStartActivityAsCaller(
             Context who, IBinder contextThread, IBinder token, Activity target,
-            Intent intent, int requestCode, Bundle options, IBinder permissionToken,
+            Intent intent, int requestCode, Bundle options,
             boolean ignoreTargetSecurity, int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
@@ -2030,7 +2034,7 @@
                     .startActivityAsCaller(whoThread, who.getOpPackageName(), intent,
                             intent.resolveTypeIfNeeded(who.getContentResolver()),
                             token, target != null ? target.mEmbeddedID : null,
-                            requestCode, 0, null, options, permissionToken,
+                            requestCode, 0, null, options,
                             ignoreTargetSecurity, userId);
             checkStartActivityResult(result, intent);
         } catch (RemoteException e) {
diff --git a/core/java/android/app/wallpapereffectsgeneration/CameraAttributes.java b/core/java/android/app/wallpapereffectsgeneration/CameraAttributes.java
index dfbc7a4..c91ce24 100644
--- a/core/java/android/app/wallpapereffectsgeneration/CameraAttributes.java
+++ b/core/java/android/app/wallpapereffectsgeneration/CameraAttributes.java
@@ -18,6 +18,7 @@
 
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
+import android.annotation.Size;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -117,6 +118,7 @@
     /**
      * Get the camera yaw orbit rotation.
      */
+    @FloatRange(from = -180.0f, to = 180.0f)
     public float getCameraOrbitYawDegrees() {
         return mCameraOrbitYawDegrees;
     }
@@ -124,6 +126,7 @@
     /**
      * Get the camera pitch orbit rotation.
      */
+    @FloatRange(from = -90.0f, to = 90.0f)
     public float getCameraOrbitPitchDegrees() {
         return mCameraOrbitPitchDegrees;
     }
@@ -138,6 +141,7 @@
     /**
      * Get the camera vertical fov degrees.
      */
+    @FloatRange(from = 0.0f, to = 180.0f, fromInclusive = false)
     public float getVerticalFovDegrees() {
         return mVerticalFovDegrees;
     }
@@ -145,6 +149,7 @@
     /**
      * Get the frustum in near plane.
      */
+    @FloatRange(from = 0.0f)
     public float getFrustumNearInWorldSpace() {
         return mFrustumNearInWorldSpace;
     }
@@ -152,6 +157,7 @@
     /**
      * Get the frustum in far plane.
      */
+    @FloatRange(from = 0.0f)
     public float getFrustumFarInWorldSpace() {
         return mFrustumFarInWorldSpace;
     }
@@ -217,8 +223,8 @@
          * @hide
          */
         @SystemApi
-        public Builder(@NonNull float[] anchorPointInWorldSpace,
-                @NonNull float[] anchorPointInOutputUvSpace) {
+        public Builder(@NonNull @Size(3) float[] anchorPointInWorldSpace,
+                @NonNull @Size(2) float[] anchorPointInOutputUvSpace) {
             mAnchorPointInWorldSpace = anchorPointInWorldSpace;
             mAnchorPointInOutputUvSpace = anchorPointInOutputUvSpace;
         }
diff --git a/core/java/android/app/wallpapereffectsgeneration/CinematicEffectResponse.java b/core/java/android/app/wallpapereffectsgeneration/CinematicEffectResponse.java
index 1254794..b1d2b38 100644
--- a/core/java/android/app/wallpapereffectsgeneration/CinematicEffectResponse.java
+++ b/core/java/android/app/wallpapereffectsgeneration/CinematicEffectResponse.java
@@ -39,27 +39,31 @@
 public final class CinematicEffectResponse implements Parcelable {
     /** @hide */
     @IntDef(prefix = {"CINEMATIC_EFFECT_STATUS_"},
-            value = {CINEMATIC_EFFECT_STATUS_UNKNOWN,
+            value = {CINEMATIC_EFFECT_STATUS_ERROR,
                     CINEMATIC_EFFECT_STATUS_OK,
-                    CINEMATIC_EFFECT_STATUS_ERROR,
                     CINEMATIC_EFFECT_STATUS_NOT_READY,
                     CINEMATIC_EFFECT_STATUS_PENDING,
-                    CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS})
+                    CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS
+            })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CinematicEffectStatusCode {}
 
-    /** Cinematic effect generation unknown status. */
-    public static final int CINEMATIC_EFFECT_STATUS_UNKNOWN = 0;
+    /** Cinematic effect generation failure with internal error. */
+    public static final int CINEMATIC_EFFECT_STATUS_ERROR = 0;
+
     /** Cinematic effect generation success. */
     public static final int CINEMATIC_EFFECT_STATUS_OK = 1;
-    /** Cinematic effect generation failure. */
-    public static final int CINEMATIC_EFFECT_STATUS_ERROR = 2;
+
     /** Service not ready for cinematic effect generation. */
-    public static final int CINEMATIC_EFFECT_STATUS_NOT_READY = 3;
-    /** Cienmatic effect generation process is pending. */
-    public static final int CINEMATIC_EFFECT_STATUS_PENDING = 4;
-    /** Too manay requests for server to handle. */
-    public static final int CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS = 5;
+    public static final int CINEMATIC_EFFECT_STATUS_NOT_READY = 2;
+    /**
+     * There is already a task being processed for the same task id.
+     * Client should wait for the response and not send the same request
+     * again.
+     */
+    public static final int CINEMATIC_EFFECT_STATUS_PENDING = 3;
+    /** Too many requests for server to handle. */
+    public static final int CINEMATIC_EFFECT_STATUS_TOO_MANY_REQUESTS = 4;
 
     /** @hide */
     @IntDef(prefix = {"IMAGE_CONTENT_TYPE_"},
@@ -71,13 +75,13 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface ImageContentType {}
 
-    /** Image content unknown. */
+    /** Unable to determine image type. */
     public static final int IMAGE_CONTENT_TYPE_UNKNOWN = 0;
     /** Image content is people portrait. */
     public static final int IMAGE_CONTENT_TYPE_PEOPLE_PORTRAIT = 1;
     /** Image content is landscape. */
     public static final int IMAGE_CONTENT_TYPE_LANDSCAPE = 2;
-    /** Image content is doesn't belong to other types. */
+    /** Image content is not people portrait or landscape. */
     public static final int IMAGE_CONTENT_TYPE_OTHER = 3;
 
 
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index a1983ca..914b321 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -469,6 +469,10 @@
         /**
          * Called when the top activity is changed.
          *
+         * <p>Note: When there are no activities running on the virtual display, the
+         * {@link #onDisplayEmpty(int)} will be called. If the value topActivity is cached, it
+         * should be cleared when {@link #onDisplayEmpty(int)} is called.
+         *
          * @param displayId The display ID on which the activity change happened.
          * @param topActivity The component name of the top activity.
          */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2c207bc..a50ff3841 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5987,22 +5987,6 @@
     public static final String EXTRA_UID = "android.intent.extra.UID";
 
     /**
-     * Used as an optional int extra field in {@link android.content.Intent#ACTION_PACKAGE_ADDED}
-     * intents to supply the previous uid the package had been assigned.
-     * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
-     * system app upgrade that had left sharedUserId is getting uninstalled.
-     */
-    public static final String EXTRA_PREVIOUS_UID = "android.intent.extra.PREVIOUS_UID";
-
-    /**
-     * Used as an optional int extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
-     * intents to supply the new uid the package will be assigned.
-     * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
-     * system app upgrade that had left sharedUserId is getting uninstalled.
-     */
-    public static final String EXTRA_NEW_UID = "android.intent.extra.NEW_UID";
-
-    /**
      * @hide String array of package names.
      */
     @SystemApi
@@ -6034,16 +6018,6 @@
     public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
 
     /**
-     * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED},
-     * {@link android.content.Intent#ACTION_UID_REMOVED}, and
-     * {@link android.content.Intent#ACTION_PACKAGE_ADDED}
-     * intents to indicate that this package is changing its UID.
-     * This would only be set when a package is leaving sharedUserId in an upgrade, or when a
-     * system app upgrade that had left sharedUserId is getting uninstalled.
-     */
-    public static final String EXTRA_UID_CHANGING = "android.intent.extra.UID_CHANGING";
-
-    /**
      * Used as an int extra field in {@link android.app.AlarmManager} pending intents
      * to tell the application being invoked how many pending alarms are being
      * delivered with the intent.  For one-shot alarms this will always be 1.
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 88ef054..236c244 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2308,8 +2308,14 @@
          *
          * <ul>
          *     <li>{@code requireUserAction} is set to {@link #USER_ACTION_NOT_REQUIRED}.</li>
-         *     <li>The app being installed targets {@link android.os.Build.VERSION_CODES#Q API 29}
-         *     or higher.</li>
+         *     <li>The app being installed targets:
+         *          <ul>
+         *              <li>{@link android.os.Build.VERSION_CODES#Q API 29} or higher on
+         *              Android S ({@link android.os.Build.VERSION_CODES#S API 31})</li>
+         *              <li>{@link android.os.Build.VERSION_CODES#R API 30} or higher after
+         *              Android S ({@link android.os.Build.VERSION_CODES#S API 31})</li>
+         *          </ul>
+         *     </li>
          *     <li>The installer is the {@link InstallSourceInfo#getInstallingPackageName()
          *     installer of record} of an existing version of the app (in other words, this install
          *     session is an app update) or the installer is updating itself.</li>
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 56d092d..52774e3 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -2241,10 +2241,20 @@
     }
 
     /**
-     * Return true if the shortcut is included in specified surface.
+     * Return true if the shortcut is excluded from specified surface.
      */
-    public boolean isIncludedIn(@Surface int surface) {
-        return (mExcludedSurfaces & surface) == 0;
+    public boolean isExcludedFromSurfaces(@Surface int surface) {
+        return (mExcludedSurfaces & surface) != 0;
+    }
+
+    /**
+     * Returns a bitmask of all surfaces this shortcut is excluded from.
+     *
+     * @see ShortcutInfo.Builder#setExcludedFromSurfaces(int)
+     */
+    @Surface
+    public int getExcludedFromSurfaces() {
+        return mExcludedSurfaces;
     }
 
     /**
@@ -2543,7 +2553,7 @@
         if (isLongLived()) {
             sb.append("Liv");
         }
-        if (!isIncludedIn(SURFACE_LAUNCHER)) {
+        if (isExcludedFromSurfaces(SURFACE_LAUNCHER)) {
             sb.append("Hid-L");
         }
         sb.append("]");
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5191c95..5bd77ab 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -86,6 +86,7 @@
 import android.util.MemoryIntArray;
 import android.view.Display;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 import android.view.Window;
 import android.view.WindowManager.LayoutParams;
 import android.widget.Editor;
@@ -7477,6 +7478,16 @@
                 "accessibility_shortcut_dialog_shown";
 
         /**
+         * Setting specifying if the timeout restriction
+         * {@link ViewConfiguration#getAccessibilityShortcutKeyTimeout()}
+         * of the accessibility shortcut dialog is skipped.
+         *
+         * @hide
+         */
+        public static final String SKIP_ACCESSIBILITY_SHORTCUT_DIALOG_TIMEOUT_RESTRICTION =
+                "skip_accessibility_shortcut_dialog_timeout_restriction";
+
+        /**
          * Setting specifying the accessibility services, accessibility shortcut targets,
          * or features to be toggled via the accessibility shortcut.
          *
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/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index b701e07..e9f099a 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -876,7 +876,7 @@
          * if (filter != null) {
          *     fieldBuilder.setFilter(filter);
          * }
-         * Presentations.Builder presentationsBuilder = new Presentations.Builder(id);
+         * Presentations.Builder presentationsBuilder = new Presentations.Builder();
          * if (presentation != null) {
          *     presentationsBuilder.setMenuPresentation(presentation);
          * }
diff --git a/core/java/android/service/autofill/Field.java b/core/java/android/service/autofill/Field.java
index 8c905a6..d63cf33 100644
--- a/core/java/android/service/autofill/Field.java
+++ b/core/java/android/service/autofill/Field.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
 import com.android.internal.util.DataClass;
@@ -26,10 +25,9 @@
 import java.util.regex.Pattern;
 
 /**
- * This class is used to set all information of a field. Such as the
- * {@link AutofillId} of the field, the {@link AutofillValue} to be autofilled,
- * a <a href="#Filtering">explicit filter</a>, and presentations to be visualized,
- * etc.
+ * This class is used to set all information of a field. Such as the {@link AutofillValue}
+ * to be autofilled, a <a href="#Filtering">explicit filter</a>, and presentations to be
+ * visualized, etc.
  */
 public final class Field {
 
diff --git a/core/java/android/service/games/GameSessionTrampolineActivity.java b/core/java/android/service/games/GameSessionTrampolineActivity.java
index ddea098..3d97d0f 100644
--- a/core/java/android/service/games/GameSessionTrampolineActivity.java
+++ b/core/java/android/service/games/GameSessionTrampolineActivity.java
@@ -51,7 +51,6 @@
             startActivityAsCaller(
                     getIntent().getParcelableExtra(INTENT_KEY),
                     getIntent().getBundleExtra(OPTIONS_KEY),
-                    null,
                     false,
                     getUserId(),
                     REQUEST_CODE);
diff --git a/core/java/android/service/trust/GrantTrustResult.java b/core/java/android/service/trust/GrantTrustResult.java
index 7cf708a..5b06bb8 100644
--- a/core/java/android/service/trust/GrantTrustResult.java
+++ b/core/java/android/service/trust/GrantTrustResult.java
@@ -32,7 +32,7 @@
  *
  * @hide
  */
-@DataClass(genHiddenConstructor = true)
+@DataClass
 @SystemApi
 public final class GrantTrustResult implements Parcelable {
 
@@ -42,15 +42,10 @@
     /** The device went from locked to unlocked as a result of the call. */
     public static final int STATUS_UNLOCKED_BY_GRANT = 1;
 
+    /** The status code of the result. */
     @Status
     private int mStatus;
 
-    /** Returns a new {@link GrantTrustResult} with the specified status. */
-    @NonNull
-    public static GrantTrustResult withStatus(@Status int status) {
-        return new GrantTrustResult(status);
-    }
-
 
 
     // Code below generated by codegen v1.0.23.
@@ -90,7 +85,8 @@
     /**
      * Creates a new GrantTrustResult.
      *
-     * @hide
+     * @param status
+     *   The status code of the result.
      */
     @DataClass.Generated.Member
     public GrantTrustResult(
@@ -109,6 +105,9 @@
         // onConstructed(); // You can define this method to get a callback
     }
 
+    /**
+     * The status code of the result.
+     */
     @DataClass.Generated.Member
     public @Status int getStatus() {
         return mStatus;
@@ -165,10 +164,10 @@
     };
 
     @DataClass.Generated(
-            time = 1647878197834L,
+            time = 1648138312806L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/trust/GrantTrustResult.java",
-            inputSignatures = "public static final  int STATUS_UNKNOWN\npublic static final  int STATUS_UNLOCKED_BY_GRANT\nprivate @android.service.trust.GrantTrustResult.Status int mStatus\npublic static @android.annotation.NonNull android.service.trust.GrantTrustResult withStatus(int)\nclass GrantTrustResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+            inputSignatures = "public static final  int STATUS_UNKNOWN\npublic static final  int STATUS_UNLOCKED_BY_GRANT\nprivate @android.service.trust.GrantTrustResult.Status int mStatus\nclass GrantTrustResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/service/wallpapereffectsgeneration/WallpaperEffectsGenerationService.java b/core/java/android/service/wallpapereffectsgeneration/WallpaperEffectsGenerationService.java
index 18b654e..2898149 100644
--- a/core/java/android/service/wallpapereffectsgeneration/WallpaperEffectsGenerationService.java
+++ b/core/java/android/service/wallpapereffectsgeneration/WallpaperEffectsGenerationService.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.CallSuper;
+import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Service;
@@ -69,7 +70,6 @@
      * {@link android.permission#MANAGE_WALLPAPER_EFFECTS_GENERATION}
      * permission.
      *
-     * @hide
      */
     public static final String SERVICE_INTERFACE =
             "android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService";
@@ -97,6 +97,7 @@
      *
      * @param request the cinematic effect request passed from the client.
      */
+    @MainThread
     public abstract void onGenerateCinematicEffect(@NonNull CinematicEffectRequest request);
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index febd2e2..7d823b1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11939,13 +11939,22 @@
     @NonNull
     List<Rect> collectPreferKeepClearRects() {
         ListenerInfo info = mListenerInfo;
-        final List<Rect> list = new ArrayList<>();
+        boolean keepBoundsClear =
+                (info != null && info.mPreferKeepClear) || mPreferKeepClearForFocus;
+        boolean hasCustomKeepClearRects = info != null && info.mKeepClearRects != null;
 
-        if ((info != null && info.mPreferKeepClear) || mPreferKeepClearForFocus) {
+        if (!keepBoundsClear && !hasCustomKeepClearRects) {
+            return Collections.emptyList();
+        } else if (keepBoundsClear && !hasCustomKeepClearRects) {
+            return Collections.singletonList(new Rect(0, 0, getWidth(), getHeight()));
+        }
+
+        final List<Rect> list = new ArrayList<>();
+        if (keepBoundsClear) {
             list.add(new Rect(0, 0, getWidth(), getHeight()));
         }
 
-        if (info != null && info.mKeepClearRects != null) {
+        if (hasCustomKeepClearRects) {
             list.addAll(info.mKeepClearRects);
         }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a3e6945..fa3834d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2338,10 +2338,9 @@
         final int systemUiFlag = publicType == Type.statusBars()
                 ? View.SYSTEM_UI_FLAG_FULLSCREEN
                 : View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-        final boolean wasVisible = (info.globalVisibility & systemUiFlag) == 0;
         if (visible) {
             info.globalVisibility &= ~systemUiFlag;
-            if (!wasVisible && hasControl) {
+            if (hasControl && (mAttachInfo.mSystemUiVisibility & systemUiFlag) != 0) {
                 // The local system UI visibility can only be cleared while we have the control.
                 info.localChanges |= systemUiFlag;
             }
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index 9793f8c..4387701 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/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 07db91f..6fa6d39 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -3077,11 +3077,26 @@
     }
 
     /**
-     * Like {@link #showAutofillDialog(View)} but for virtual views.
+     * If autofill suggestions for a
+     * <a href="{@docRoot}reference/android/service/autofill/Dataset.html#FillDialogUI">
+     * dialog-style UI</a> are available for virtual {@code view}, shows a dialog allowing the user
+     * to select a suggestion and returns {@code true}.
+     * <p>
+     * The dialog may not be shown if the autofill service does not support it, if the autofill
+     * request has not returned a response yet, if the dialog was shown previously, or if the
+     * input method is already shown.
+     * <p>
+     * It is recommended apps to call this method the first time a user focuses on
+     * an autofill-able form, and to avoid showing the input method if the dialog is shown. If
+     * this method returns {@code false}, you should then instead show the input method (assuming
+     * that is how the view normally handles the focus event). If the user re-focuses on the view,
+     * you should not call this method again so as to not disrupt usage of the input method.
      *
-     * @param virtualId id identifying the virtual child inside the parent view.
+     * @param view the view hosting the virtual view hierarchy which is used to show autofill
+     *            suggestions.
+     * @param virtualId id identifying the virtual view inside the host view.
+     * @return {@code true} if the autofill dialog is being shown
      */
-    // TODO(b/210926084): Consider whether to include the one-time show logic within this method.
     public boolean showAutofillDialog(@NonNull View view, int virtualId) {
         Objects.requireNonNull(view);
         if (shouldShowAutofillDialog(getAutofillId(view, virtualId))) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c2e145e..96728ed 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -28,7 +28,6 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
 import android.app.SharedElementCallback;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionManager;
@@ -71,11 +70,9 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -761,25 +758,17 @@
             return false;
         }
 
-        try {
-            Intent delegationIntent = new Intent();
-            final ComponentName delegateActivity = ComponentName.unflattenFromString(
-                    Resources.getSystem().getString(R.string.config_chooserActivity));
-            IBinder permissionToken = ActivityTaskManager.getService()
-                    .requestStartActivityPermissionToken(delegateActivity);
-            delegationIntent.setComponent(delegateActivity);
-            delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent());
-            delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
-            delegationIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+        Intent delegationIntent = new Intent();
+        final ComponentName delegateActivity = ComponentName.unflattenFromString(
+                Resources.getSystem().getString(R.string.config_chooserActivity));
+        delegationIntent.setComponent(delegateActivity);
+        delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent());
+        delegationIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
 
-            // Don't close until the delegate finishes, or the token will be invalidated.
-            mAwaitingDelegateResponse = true;
-            startActivityForResult(delegationIntent, REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER);
-            return true;
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
-        return false;
+        // Don't close until the delegate finishes, or the token will be invalidated.
+        mAwaitingDelegateResponse = true;
+        startActivityForResult(delegationIntent, REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER);
+        return true;
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 6e76906..070d8ff 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -207,7 +207,6 @@
             startActivityAsCaller(
                     newIntent,
                     /* options= */ null,
-                    /* permissionToken= */ null,
                     /* ignoreTargetSecurity= */ false,
                     userId);
         } catch (RuntimeException e) {
@@ -231,7 +230,7 @@
             return;
         }
         sanitizeIntent(innerIntent);
-        startActivityAsCaller(intentReceived, null, null, false, getUserId());
+        startActivityAsCaller(intentReceived, null, false, getUserId());
         finish();
     }
 
@@ -251,7 +250,7 @@
         sanitizeIntent(intentReceived);
         intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
         intentReceived.putExtra(EXTRA_CALLING_USER, UserHandle.of(callingUserId));
-        startActivityAsCaller(intentReceived, null, null, false, userId);
+        startActivityAsCaller(intentReceived, null, false, userId);
         finish();
     }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 5ebb148..dc68e16 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1463,7 +1463,7 @@
             int userId) {
         // Note: this method will be overridden in the delegate implementation to use the passed-in
         // permission token.
-        startActivityAsCaller(intent, options, null, false, userId);
+        startActivityAsCaller(intent, options, false, userId);
         return true;
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f623a73..4b20347 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -69,6 +69,7 @@
 import android.os.connectivity.WifiActivityEnergyInfo;
 import android.os.connectivity.WifiBatteryStats;
 import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthLte;
@@ -6830,6 +6831,27 @@
         }
     }
 
+    @RadioAccessTechnology
+    private static int mapRadioAccessNetworkTypeToRadioAccessTechnology(
+            @AccessNetworkConstants.RadioAccessNetworkType int dataType) {
+        switch (dataType) {
+            case AccessNetworkConstants.AccessNetworkType.NGRAN:
+                return RADIO_ACCESS_TECHNOLOGY_NR;
+            case AccessNetworkConstants.AccessNetworkType.EUTRAN:
+                return RADIO_ACCESS_TECHNOLOGY_LTE;
+            case AccessNetworkConstants.AccessNetworkType.UNKNOWN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.GERAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.UTRAN: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.CDMA2000: //fallthrough
+            case AccessNetworkConstants.AccessNetworkType.IWLAN:
+                return RADIO_ACCESS_TECHNOLOGY_OTHER;
+            default:
+                Slog.w(TAG,
+                        "Unhandled RadioAccessNetworkType (" + dataType + "), mapping to OTHER");
+                return RADIO_ACCESS_TECHNOLOGY_OTHER;
+        }
+    }
+
     @GuardedBy("this")
     public void noteWifiOnLocked() {
         noteWifiOnLocked(mClock.elapsedRealtime(), mClock.uptimeMillis());
@@ -13721,66 +13743,7 @@
                     mTmpRailStats.resetCellularTotalEnergyUsed();
                 }
 
-                // Proportionally smear Rx and Tx times across each RAt
-                final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
-                long[] perSignalStrengthActiveTimeMs = new long[levelCount];
-                long totalActiveTimeMs = 0;
-
-                for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
-                    final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
-                    if (ratStats == null) continue;
-
-                    final int freqCount = ratStats.getFrequencyRangeCount();
-                    for (int freq = 0; freq < freqCount; freq++) {
-                        for (int level = 0; level < levelCount; level++) {
-                            final long durationMs = ratStats.getTimeSinceMark(freq, level,
-                                    elapsedRealtimeMs);
-                            perSignalStrengthActiveTimeMs[level] += durationMs;
-                            totalActiveTimeMs += durationMs;
-                        }
-                    }
-                }
-
-                if (totalActiveTimeMs != 0) {
-                    // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
-                    // strength.
-                    for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
-                        final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
-                        if (ratStats == null) continue;
-
-                        final int freqCount = ratStats.getFrequencyRangeCount();
-                        for (int freq = 0; freq < freqCount; freq++) {
-                            long frequencyDurationMs = 0;
-                            for (int level = 0; level < levelCount; level++) {
-                                final long durationMs = ratStats.getTimeSinceMark(freq, level,
-                                        elapsedRealtimeMs);
-                                final long totalLvlDurationMs =
-                                        perSignalStrengthActiveTimeMs[level];
-                                if (totalLvlDurationMs == 0) continue;
-                                final long totalTxLvlDurations =
-                                        deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
-                                // Smear HAL provided Tx power level duration based on active modem
-                                // duration in a given state. (Add totalLvlDurationMs / 2 before
-                                // the integer division with totalLvlDurationMs for rounding.)
-                                final long proportionalTxDurationMs =
-                                        (durationMs * totalTxLvlDurations
-                                                + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
-                                ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
-                                frequencyDurationMs += durationMs;
-                            }
-                            final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
-                            // Smear HAL provided Rx power duration based on active modem
-                            // duration in a given state.  (Add totalActiveTimeMs / 2 before the
-                            // integer division with totalActiveTimeMs for rounding.)
-                            final long proportionalRxDurationMs =
-                                    (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
-                                            / 2)) / totalActiveTimeMs;
-                            ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
-                        }
-
-                        ratStats.setMark(elapsedRealtimeMs);
-                    }
-                }
+                incrementPerRatDataLocked(deltaInfo, elapsedRealtimeMs);
             }
             long totalAppRadioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
                     elapsedRealtimeMs * 1000);
@@ -13931,6 +13894,100 @@
         }
     }
 
+    @GuardedBy("this")
+    private void incrementPerRatDataLocked(ModemActivityInfo deltaInfo, long elapsedRealtimeMs) {
+        final int infoSize = deltaInfo.getSpecificInfoLength();
+        if (infoSize == 1 && deltaInfo.getSpecificInfoRat(0)
+                == AccessNetworkConstants.AccessNetworkType.UNKNOWN
+                && deltaInfo.getSpecificInfoFrequencyRange(0)
+                == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+            // Specific info data unavailable. Proportionally smear Rx and Tx times across each RAT.
+            final int levelCount = CellSignalStrength.getNumSignalStrengthLevels();
+            long[] perSignalStrengthActiveTimeMs = new long[levelCount];
+            long totalActiveTimeMs = 0;
+
+            for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+                final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+                if (ratStats == null) continue;
+
+                final int freqCount = ratStats.getFrequencyRangeCount();
+                for (int freq = 0; freq < freqCount; freq++) {
+                    for (int level = 0; level < levelCount; level++) {
+                        final long durationMs = ratStats.getTimeSinceMark(freq, level,
+                                elapsedRealtimeMs);
+                        perSignalStrengthActiveTimeMs[level] += durationMs;
+                        totalActiveTimeMs += durationMs;
+                    }
+                }
+            }
+            if (totalActiveTimeMs != 0) {
+                // Smear the provided Tx/Rx durations across each RAT, frequency, and signal
+                // strength.
+                for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+                    final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+                    if (ratStats == null) continue;
+
+                    final int freqCount = ratStats.getFrequencyRangeCount();
+                    for (int freq = 0; freq < freqCount; freq++) {
+                        long frequencyDurationMs = 0;
+                        for (int level = 0; level < levelCount; level++) {
+                            final long durationMs = ratStats.getTimeSinceMark(freq, level,
+                                    elapsedRealtimeMs);
+                            final long totalLvlDurationMs =
+                                    perSignalStrengthActiveTimeMs[level];
+                            if (totalLvlDurationMs == 0) continue;
+                            final long totalTxLvlDurations =
+                                    deltaInfo.getTransmitDurationMillisAtPowerLevel(level);
+                            // Smear HAL provided Tx power level duration based on active modem
+                            // duration in a given state. (Add totalLvlDurationMs / 2 before
+                            // the integer division with totalLvlDurationMs for rounding.)
+                            final long proportionalTxDurationMs =
+                                    (durationMs * totalTxLvlDurations
+                                            + (totalLvlDurationMs / 2)) / totalLvlDurationMs;
+                            ratStats.incrementTxDuration(freq, level, proportionalTxDurationMs);
+                            frequencyDurationMs += durationMs;
+                        }
+                        final long totalRxDuration = deltaInfo.getReceiveTimeMillis();
+                        // Smear HAL provided Rx power duration based on active modem
+                        // duration in a given state.  (Add totalActiveTimeMs / 2 before the
+                        // integer division with totalActiveTimeMs for rounding.)
+                        final long proportionalRxDurationMs =
+                                (frequencyDurationMs * totalRxDuration + (totalActiveTimeMs
+                                        / 2)) / totalActiveTimeMs;
+                        ratStats.incrementRxDuration(freq, proportionalRxDurationMs);
+                    }
+
+                }
+            }
+        } else {
+            // Specific data available.
+            for (int index = 0; index < infoSize; index++) {
+                final int rat = deltaInfo.getSpecificInfoRat(index);
+                final int freq = deltaInfo.getSpecificInfoFrequencyRange(index);
+
+                // Map RadioAccessNetworkType to course grain RadioAccessTechnology.
+                final int ratBucket = mapRadioAccessNetworkTypeToRadioAccessTechnology(rat);
+                final RadioAccessTechnologyBatteryStats ratStats = getRatBatteryStatsLocked(
+                        ratBucket);
+
+                final long rxTimeMs = deltaInfo.getReceiveTimeMillis(rat, freq);
+                final int[] txTimesMs = deltaInfo.getTransmitTimeMillis(rat, freq);
+
+                ratStats.incrementRxDuration(freq, rxTimeMs);
+                final int numTxLvl = txTimesMs.length;
+                for (int lvl = 0; lvl < numTxLvl; lvl++) {
+                    ratStats.incrementTxDuration(freq, lvl, txTimesMs[lvl]);
+                }
+            }
+        }
+
+        for (int rat = 0; rat < RADIO_ACCESS_TECHNOLOGY_COUNT; rat++) {
+            final RadioAccessTechnologyBatteryStats ratStats = mPerRatBatteryStats[rat];
+            if (ratStats == null) continue;
+            ratStats.setMark(elapsedRealtimeMs);
+        }
+    }
+
     /**
      * Add modem tx power to history
      * Device is said to be in high cellular transmit power when it has spent most of the transmit
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ae56af6..0353e4b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -719,6 +719,92 @@
     <protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
     <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" />
 
+    <!-- Moved from packages/services/Telephony in T -->
+    <protected-broadcast android:name="android.telecom.action.CURRENT_TTY_MODE_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.SERVICE_STATE" />
+    <protected-broadcast android:name="android.intent.action.RADIO_TECHNOLOGY" />
+    <protected-broadcast android:name="android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.EMERGENCY_CALL_STATE_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.SIG_STR" />
+    <protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+    <protected-broadcast android:name="android.intent.action.DATA_STALL_DETECTED" />
+    <protected-broadcast android:name="android.intent.action.SIM_STATE_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
+    <protected-broadcast android:name="android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS" />
+    <protected-broadcast android:name="android.intent.action.ACTION_MDN_STATE_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.SERVICE_PROVIDERS_UPDATED" />
+    <protected-broadcast android:name="android.provider.Telephony.SIM_FULL" />
+    <protected-broadcast android:name="com.android.internal.telephony.carrier_key_download_alarm" />
+    <protected-broadcast android:name="com.android.internal.telephony.data-restart-trysetup" />
+    <protected-broadcast android:name="com.android.internal.telephony.data-stall" />
+    <protected-broadcast android:name="com.android.internal.telephony.provisioning_apn_alarm" />
+    <protected-broadcast android:name="android.intent.action.DATA_SMS_RECEIVED" />
+    <protected-broadcast android:name="android.provider.Telephony.SMS_RECEIVED" />
+    <protected-broadcast android:name="android.provider.Telephony.SMS_DELIVER" />
+    <protected-broadcast android:name="android.provider.Telephony.SMS_REJECTED" />
+    <protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+    <protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
+    <protected-broadcast android:name="android.provider.Telephony.SMS_CB_RECEIVED" />
+    <protected-broadcast android:name="android.provider.action.SMS_EMERGENCY_CB_RECEIVED" />
+    <protected-broadcast android:name="android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED" />
+    <protected-broadcast android:name="android.provider.Telephony.SECRET_CODE" />
+    <protected-broadcast android:name="com.android.internal.stk.command" />
+    <protected-broadcast android:name="com.android.internal.stk.session_end" />
+    <protected-broadcast android:name="com.android.internal.stk.icc_status_change" />
+    <protected-broadcast android:name="com.android.internal.stk.alpha_notify" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+    <protected-broadcast android:name="com.android.internal.telephony.PROVISION" />
+    <protected-broadcast android:name="com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED" />
+    <protected-broadcast android:name="com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED" />
+    <protected-broadcast android:name="com.android.intent.isim_refresh" />
+    <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_AVAILABLE" />
+    <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_UNAVAILABLE" />
+    <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_DIED" />
+    <protected-broadcast android:name="com.android.ims.ACTION_PRESENCE_CHANGED" />
+    <protected-broadcast android:name="com.android.ims.ACTION_PUBLISH_STATUS_CHANGED" />
+    <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
+    <protected-broadcast android:name="com.android.ims.IMS_SERVICE_DOWN" />
+    <protected-broadcast android:name="com.android.ims.IMS_INCOMING_CALL" />
+    <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
+    <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_DOWN" />
+    <protected-broadcast android:name="com.android.imsconnection.DISCONNECTED" />
+    <protected-broadcast android:name="com.android.intent.action.IMS_FEATURE_CHANGED" />
+    <protected-broadcast android:name="com.android.intent.action.IMS_CONFIG_CHANGED" />
+    <protected-broadcast android:name="android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR" />
+    <protected-broadcast android:name="com.android.phone.vvm.omtp.sms.REQUEST_SENT" />
+    <protected-broadcast android:name="com.android.phone.vvm.ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT" />
+    <protected-broadcast android:name="com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
+    <protected-broadcast android:name="com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
+    <protected-broadcast android:name="com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" />
+    <protected-broadcast android:name="com.android.internal.telephony.action.COUNTRY_OVERRIDE" />
+    <protected-broadcast android:name="com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" />
+    <protected-broadcast android:name="com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID" />
+    <protected-broadcast android:name="android.telephony.action.SIM_CARD_STATE_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.TOGGLE_PROVISION" />
+    <protected-broadcast android:name="android.telephony.action.NETWORK_COUNTRY_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.MULTI_SIM_CONFIG_CHANGED" />
+    <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_RESET" />
+    <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_PCO_VALUE" />
+    <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+    <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_REDIRECTED" />
+    <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED" />
+    <protected-broadcast android:name="com.android.phone.settings.CARRIER_PROVISIONING" />
+    <protected-broadcast android:name="com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING" />
+    <protected-broadcast android:name="com.android.internal.telephony.ACTION_VOWIFI_ENABLED" />
+    <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
+    <protected-broadcast android:name="android.intent.action.SUBSCRIPTION_INFO_RECORD_ADDED" />
+    <protected-broadcast android:name="android.intent.action.ACTION_MANAGED_ROAMING_IND" />
+    <protected-broadcast android:name="android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE" />
+
     <!-- Added in T -->
     <protected-broadcast android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES" />
     <protected-broadcast android:name="android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED" />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 579ef51..7562b9a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -401,15 +401,6 @@
          and before. -->
     <attr name="sharedUserMaxSdkVersion" format="integer" />
 
-    <!-- Whether the application should inherit all AndroidKeyStore keys of its shared user
-         group in the case of leaving its shared user ID in an upgrade.  If set to false, all
-         AndroidKeyStore keys will remain in the shared user group, and the application will no
-         longer have access to those keys after the upgrade. If set to true, all AndroidKeyStore
-         keys owned by the shared user group will be transferred to the upgraded application;
-         other applications in the shared user group will no longer have access to those keys
-         after the migration. The default value is false if not explicitly set. -->
-    <attr name="inheritKeyStoreKeys" format="boolean" />
-
     <!-- Internal version code.  This is the number used to determine whether
          one version is more recent than another: it has no other meaning than
          that higher numbers are more recent.  You could use this number to
@@ -1704,7 +1695,6 @@
         <attr name="sharedUserId" />
         <attr name="sharedUserLabel" />
         <attr name="sharedUserMaxSdkVersion" />
-        <attr name="inheritKeyStoreKeys" />
         <attr name="installLocation" />
         <attr name="isolatedSplits" />
         <attr name="isFeatureSplit" />
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index 0756911..aaf6a41 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -128,7 +128,7 @@
     <public name="localeConfig" />
     <public name="showBackground" />
     <public name="useTargetActivityForQuickAccess"/>
-    <public name="inheritKeyStoreKeys" />
+    <public name="removed_inheritKeyStoreKeys" />
     <public name="preferKeepClear" />
     <public name="autoHandwritingEnabled" />
     <public name="fromExtendLeft" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d30980f..f11fd92 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6279,7 +6279,9 @@
 
     <!-- Strings for VirtualDeviceManager -->
     <!-- Error message indicating the camera cannot be accessed when running on a virtual device. [CHAR LIMIT=NONE] -->
-    <string name="vdm_camera_access_denied">Cannot access camera from this device</string>
+    <string name="vdm_camera_access_denied" product="default">Can’t access the phone’s camera from your <xliff:g id="device" example="Chromebook">%1$s</xliff:g></string>
+    <!-- Error message indicating the camera cannot be accessed when running on a virtual device. [CHAR LIMIT=NONE] -->
+    <string name="vdm_camera_access_denied" product="tablet">Can’t access the tablet’s camera from your <xliff:g id="device" example="Chromebook">%1$s</xliff:g></string>
 
     <!-- Title for preference of the system default locale. [CHAR LIMIT=50]-->
     <string name="system_locale_title">System language</string>
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index 1f6b57e..a663095 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -44,7 +44,6 @@
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -649,7 +648,7 @@
 
         @Override
         public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
-                IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
+                boolean ignoreTargetSecurity, int userId) {
             mStartActivityIntent = intent;
             mUserIdActivityLaunchedIn = userId;
         }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index dbe1e81..87c45dc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -32,12 +32,15 @@
 
 import android.app.ActivityManager;
 import android.app.usage.NetworkStatsManager;
+import android.hardware.radio.V1_5.AccessNetwork;
 import android.os.BatteryStats;
 import android.os.BatteryStats.HistoryItem;
 import android.os.BatteryStats.Uid.Sensor;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.ActivityStatsTechSpecificInfo;
 import android.telephony.Annotation;
 import android.telephony.CellSignalStrength;
 import android.telephony.DataConnectionRealTimeInfo;
@@ -58,8 +61,10 @@
 
 import org.mockito.Mock;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.function.IntConsumer;
 
@@ -1322,7 +1327,7 @@
             }
         }
 
-        final ModemAndBatteryState state = new ModemAndBatteryState(bi, null);
+        final ModemAndBatteryState state = new ModemAndBatteryState(bi, null, null);
 
         IntConsumer incrementTime = inc -> {
             state.currentTimeMs += inc;
@@ -1469,32 +1474,16 @@
         final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
         for (int rat = 0; rat < ratCount; rat++) {
             for (int freq = 0; freq < frequencyCount; freq++) {
-                if (rat != RADIO_ACCESS_TECHNOLOGY_NR
-                        && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
-                    // Only the NR RAT should have per frequency data.
-                    expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
-                } else {
-                    expectedRxDurationsMs[rat][freq] = 0;
-                }
                 expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
 
                 for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
-                    expectedDurationsMs[rat][freq][txLvl] = 0;
-
-                    if (rat != RADIO_ACCESS_TECHNOLOGY_NR
-                            && freq != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
-                        // Only the NR RAT should have per frequency data.
-                        expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
-                    } else {
-                        expectedTxDurationsMs[rat][freq][txLvl] = 0;
-                    }
                     expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
                 }
             }
         }
 
         final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, new int[txLevelCount], 0L);
-        final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai);
+        final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai, null);
 
         IntConsumer incrementTime = inc -> {
             state.currentTimeMs += inc;
@@ -1711,6 +1700,288 @@
                 expectedTxDurationsMs, bi, state.currentTimeMs);
     }
 
+    @SmallTest
+    public void testGetPerStateActiveRadioDurationMs_withSpecificInfoModemActivity() {
+        final MockClock clock = new MockClock(); // holds realtime and uptime in ms
+        final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
+        bi.setPowerProfile(mock(PowerProfile.class));
+        final int ratCount = RADIO_ACCESS_TECHNOLOGY_COUNT;
+        final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
+        final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
+
+        List<ActivityStatsTechSpecificInfo> specificInfoList = new ArrayList();
+
+        final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+        final long[][] expectedRxDurationsMs = new long[ratCount][frequencyCount];
+        final long[][][] expectedTxDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+        for (int rat = 0; rat < ratCount; rat++) {
+            for (int freq = 0; freq < frequencyCount; freq++) {
+                if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+                        || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                    // Initialize available specific Modem info
+                    specificInfoList.add(
+                            new ActivityStatsTechSpecificInfo(rat, freq, new int[txLevelCount], 0));
+                }
+                expectedRxDurationsMs[rat][freq] = POWER_DATA_UNAVAILABLE;
+
+                for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+                    expectedTxDurationsMs[rat][freq][txLvl] = POWER_DATA_UNAVAILABLE;
+                }
+            }
+        }
+
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UNKNOWN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.GERAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.UTRAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.EUTRAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.CDMA2000,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.IWLAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+                ServiceState.FREQUENCY_RANGE_UNKNOWN, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+                ServiceState.FREQUENCY_RANGE_LOW, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+                ServiceState.FREQUENCY_RANGE_MID, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+                ServiceState.FREQUENCY_RANGE_HIGH, new int[txLevelCount], 0));
+        specificInfoList.add(new ActivityStatsTechSpecificInfo(AccessNetwork.NGRAN,
+                ServiceState.FREQUENCY_RANGE_MMWAVE, new int[txLevelCount], 0));
+
+        final ActivityStatsTechSpecificInfo[] specificInfos = specificInfoList.toArray(
+                new ActivityStatsTechSpecificInfo[specificInfoList.size()]);
+        final ModemActivityInfo mai = new ModemActivityInfo(0L, 0L, 0L, specificInfos);
+        final ModemAndBatteryState state = new ModemAndBatteryState(bi, mai, specificInfos);
+
+        IntConsumer incrementTime = inc -> {
+            state.currentTimeMs += inc;
+            clock.realtime = clock.uptime = state.currentTimeMs;
+
+            // If the device is not on battery, no timers should increment.
+            if (!state.onBattery) return;
+            // If the modem is not active, no timers should increment.
+            if (!state.modemActive) return;
+
+            final int currRat = state.currentRat;
+            final int currRant = state.currentRadioAccessNetworkType;
+            final int currFreqRange =
+                    currRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
+            int currSignalStrength = state.currentSignalStrengths.get(currRat);
+
+            expectedDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+
+            // Evaluate the HAL provided time in states.
+            final ActivityStatsTechSpecificInfo info = state.getSpecificInfo(currRant,
+                    currFreqRange);
+            switch (state.modemState) {
+                case SLEEP:
+                    long sleepMs = state.modemActivityInfo.getSleepTimeMillis();
+                    state.modemActivityInfo.setSleepTimeMillis(sleepMs + inc);
+                    break;
+                case IDLE:
+                    long idleMs = state.modemActivityInfo.getIdleTimeMillis();
+                    state.modemActivityInfo.setIdleTimeMillis(idleMs + inc);
+                    break;
+                case RECEIVING:
+                    long rxMs = info.getReceiveTimeMillis();
+                    info.setReceiveTimeMillis(rxMs + inc);
+                    expectedRxDurationsMs[currRat][currFreqRange] += inc;
+                    break;
+                case TRANSMITTING:
+                    int[] txMs = info.getTransmitTimeMillis().clone();
+                    txMs[currSignalStrength] += inc;
+                    info.setTransmitTimeMillis(txMs);
+                    expectedTxDurationsMs[currRat][currFreqRange][currSignalStrength] += inc;
+                    break;
+            }
+        };
+
+        state.setOnBattery(false);
+        state.setModemActive(false);
+        state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                AccessNetworkConstants.AccessNetworkType.UNKNOWN);
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // While not on battery, the timers should not increase.
+        state.setModemActive(true);
+        incrementTime.accept(100);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+                AccessNetworkConstants.AccessNetworkType.NGRAN);
+        incrementTime.accept(200);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+                CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+        incrementTime.accept(500);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
+        incrementTime.accept(300);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                AccessNetworkConstants.AccessNetworkType.EUTRAN);
+        incrementTime.accept(400);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
+        incrementTime.accept(500);
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Data will now be available.
+        for (int rat = 0; rat < ratCount; rat++) {
+            for (int freq = 0; freq < frequencyCount; freq++) {
+                if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+                        || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                    // Only the NR RAT should have per frequency data.
+                    expectedRxDurationsMs[rat][freq] = 0;
+                }
+                for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+                    if (rat == RADIO_ACCESS_TECHNOLOGY_NR
+                            || freq == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+                        // Only the NR RAT should have per frequency data.
+                        expectedTxDurationsMs[rat][freq][txLvl] = 0;
+                    }
+                }
+            }
+        }
+
+        // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
+        // start counting up.
+        state.setOnBattery(true);
+        state.noteModemControllerActivity();
+        incrementTime.accept(300);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(500);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(600);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+        // Changing LTE signal strength should be tracked.
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_POOR);
+        incrementTime.accept(300);
+        state.setModemState(ModemState.SLEEP);
+        incrementTime.accept(1000);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(700);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+        incrementTime.accept(800);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(222);
+        state.setModemState(ModemState.IDLE);
+        incrementTime.accept(111);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(7777);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+        incrementTime.accept(88);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(900);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+                CellSignalStrength.SIGNAL_STRENGTH_GREAT);
+        incrementTime.accept(123);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(333);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1000);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(555);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Change in the signal strength of nonactive RAT should not affect anything.
+        state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                CellSignalStrength.SIGNAL_STRENGTH_POOR);
+        incrementTime.accept(631);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(321);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(99);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Changing to OTHER Rat should start tracking the poor signal strength.
+        state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
+                BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+                AccessNetworkConstants.AccessNetworkType.CDMA2000);
+        incrementTime.accept(1200);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Noting frequency change should not affect non NR Rat.
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
+        incrementTime.accept(444);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1300);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
+        state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+                AccessNetworkConstants.AccessNetworkType.NGRAN);
+        incrementTime.accept(1400);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Frequency changed to low.
+        state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
+        incrementTime.accept(852);
+        state.setModemState(ModemState.RECEIVING);
+        incrementTime.accept(157);
+        state.setModemState(ModemState.TRANSMITTING);
+        incrementTime.accept(1500);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+
+        // Modem no longer active, should not be tracking any more.
+        state.setModemActive(false);
+        incrementTime.accept(1500);
+        state.noteModemControllerActivity();
+        checkPerStateActiveRadioDurations(expectedDurationsMs, expectedRxDurationsMs,
+                expectedTxDurationsMs, bi, state.currentTimeMs);
+    }
+
     private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
         // Note that noteUidProcessStateLocked uses ActivityManager process states.
         if (fgOn) {
@@ -1841,17 +2112,22 @@
         public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         @BatteryStats.RadioAccessTechnology
         public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+        @AccessNetworkConstants.RadioAccessNetworkType
+        public int currentRadioAccessNetworkType = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
         @ServiceState.FrequencyRange
         public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
         public SparseIntArray currentSignalStrengths = new SparseIntArray();
         public ModemState modemState = ModemState.SLEEP;
         public ModemActivityInfo modemActivityInfo;
+        public ActivityStatsTechSpecificInfo[] specificInfo;
 
         private final MockBatteryStatsImpl mBsi;
 
-        ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai) {
+        ModemAndBatteryState(MockBatteryStatsImpl bsi, ModemActivityInfo mai,
+                ActivityStatsTechSpecificInfo[] astsi) {
             mBsi = bsi;
             modemActivityInfo = mai;
+            specificInfo = astsi;
         }
 
         void setOnBattery(boolean onBattery) {
@@ -1871,6 +2147,13 @@
         }
 
         void setRatType(@Annotation.NetworkType int dataType,
+                @BatteryStats.RadioAccessTechnology int rat,
+                @AccessNetworkConstants.RadioAccessNetworkType int halDataType) {
+            currentRadioAccessNetworkType = halDataType;
+            setRatType(dataType, rat);
+        }
+
+        void setRatType(@Annotation.NetworkType int dataType,
                 @BatteryStats.RadioAccessTechnology int rat) {
             currentNetworkDataType = dataType;
             currentRat = rat;
@@ -1895,13 +2178,45 @@
             modemState = state;
         }
 
+        ActivityStatsTechSpecificInfo getSpecificInfo(@BatteryStats.RadioAccessTechnology int rat,
+                @ServiceState.FrequencyRange int frequency) {
+            if (specificInfo == null) return null;
+            for (ActivityStatsTechSpecificInfo info : specificInfo) {
+                if (info.getRat() == rat && info.getFrequencyRange() == frequency) {
+                    return info;
+                }
+            }
+            return null;
+        }
+
         void noteModemControllerActivity() {
             if (modemActivityInfo == null) return;
             modemActivityInfo.setTimestamp(currentTimeMs);
-            ModemActivityInfo copy = new ModemActivityInfo(modemActivityInfo.getTimestampMillis(),
-                    modemActivityInfo.getSleepTimeMillis(), modemActivityInfo.getIdleTimeMillis(),
-                    modemActivityInfo.getTransmitTimeMillis().clone(),
-                    modemActivityInfo.getReceiveTimeMillis());
+            final ModemActivityInfo copy;
+            if (specificInfo == null) {
+                copy = new ModemActivityInfo(
+                        modemActivityInfo.getTimestampMillis(),
+                        modemActivityInfo.getSleepTimeMillis(),
+                        modemActivityInfo.getIdleTimeMillis(),
+                        modemActivityInfo.getTransmitTimeMillis().clone(),
+                        modemActivityInfo.getReceiveTimeMillis());
+            } else {
+                // Deep copy specificInfo
+                final ActivityStatsTechSpecificInfo[] infoCopies =
+                        new ActivityStatsTechSpecificInfo[specificInfo.length];
+                for (int i = 0; i < specificInfo.length; i++) {
+                    final ActivityStatsTechSpecificInfo info = specificInfo[i];
+                    infoCopies[i] = new ActivityStatsTechSpecificInfo(info.getRat(),
+                            info.getFrequencyRange(), info.getTransmitTimeMillis().clone(),
+                            (int) info.getReceiveTimeMillis());
+                }
+
+                copy = new ModemActivityInfo(
+                        modemActivityInfo.getTimestampMillis(),
+                        modemActivityInfo.getSleepTimeMillis(),
+                        modemActivityInfo.getIdleTimeMillis(),
+                        infoCopies);
+            }
             mBsi.noteModemControllerActivity(copy, POWER_DATA_UNAVAILABLE,
                     currentTimeMs, currentTimeMs, mNetworkStatsManager);
         }
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index bd0e56a..c81473d 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -416,6 +416,8 @@
 key usage 0x0c006F BRIGHTNESS_UP
 key usage 0x0c0070 BRIGHTNESS_DOWN
 key usage 0x0c0173 MEDIA_AUDIO_TRACK
+key usage 0x0c019C PROFILE_SWITCH
+key usage 0x0c01A2 ALL_APPS
 
 # Joystick and game controller axes.
 # Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
diff --git a/data/keyboards/Vendor_0957_Product_0001.kl b/data/keyboards/Vendor_0957_Product_0001.kl
index 672abef..13b4096 100644
--- a/data/keyboards/Vendor_0957_Product_0001.kl
+++ b/data/keyboards/Vendor_0957_Product_0001.kl
@@ -44,6 +44,8 @@
 key 11    0
 
 # custom keys
+key usage 0x000c019C    PROFILE_SWITCH
+key usage 0x000c01A2    ALL_APPS
 key usage 0x000c01BB    TV_INPUT
 key usage 0x000c022A    BOOKMARK
 key usage 0x000c0096    SETTINGS
@@ -53,6 +55,7 @@
 key usage 0x000c009C    CHANNEL_UP
 key usage 0x000c009D    CHANNEL_DOWN
 key usage 0x000c00CD    MEDIA_PLAY_PAUSE
+key usage 0x000c00B2    MEDIA_RECORD
 key usage 0x000c00B4    MEDIA_SKIP_BACKWARD
 key usage 0x000c00B3    MEDIA_SKIP_FORWARD
 key usage 0x000c0226    MEDIA_STOP
@@ -62,6 +65,7 @@
 key usage 0x000c0079    BUTTON_6     WAKE #Disney+
 key usage 0x000c007A    BUTTON_7     WAKE #HBOmax
 
+key usage 0x00070037    PERIOD
 key usage 0x000c01BD    INFO
 key usage 0x000c0061    CAPTIONS
 key usage 0x000c0185    TV_TELETEXT
diff --git a/libs/WindowManager/Jetpack/tests/unittest/Android.bp b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
new file mode 100644
index 0000000..62e8128
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/Android.bp
@@ -0,0 +1,52 @@
+// 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "WMJetpackUnitTests",
+
+    srcs: [
+        "**/*.java",
+    ],
+
+    static_libs: [
+        "androidx.window.extensions",
+        "junit",
+        "androidx.test.runner",
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "mockito-target-extended-minus-junit4",
+        "truth-prebuilt",
+        "testables",
+        "platform-test-annotations",
+    ],
+
+    libs: [
+        "android.test.mock",
+        "android.test.base",
+        "android.test.runner",
+    ],
+
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
new file mode 100644
index 0000000..b12b6f6
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="androidx.window.tests">
+
+    <application android:debuggable="true" android:largeHeap="true">
+        <uses-library android:name="android.test.mock" />
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:label="Tests for WindowManager Jetpack library"
+        android:targetPackage="androidx.window.tests">
+    </instrumentation>
+</manifest>
diff --git a/libs/WindowManager/Jetpack/tests/unittest/AndroidTest.xml b/libs/WindowManager/Jetpack/tests/unittest/AndroidTest.xml
new file mode 100644
index 0000000..56d8c33
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs Tests for WindowManager Jetpack library">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="WMJetpackUnitTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="framework-base-presubmit" />
+    <option name="test-tag" value="WMJetpackUnitTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="androidx.window.tests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
new file mode 100644
index 0000000..b6df876
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/WindowExtensionsTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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 androidx.window.extensions;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowExtensionsTest {
+    private WindowExtensions mExtensions;
+
+    @Before
+    public void setUp() {
+        mExtensions = WindowExtensionsProvider.getWindowExtensions();
+    }
+
+    @Test
+    public void testGetWindowLayoutComponent() {
+        assertThat(mExtensions.getWindowLayoutComponent()).isNotNull();
+    }
+
+    @Test
+    public void testGetActivityEmbeddingComponent() {
+        assertThat(mExtensions.getActivityEmbeddingComponent()).isNotNull();
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index da8308e..10ff2fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -692,6 +692,7 @@
      * @param bubblePosition the x position of the bubble if showing on top, the y position of
      *                       the bubble if showing vertically.
      * @param onLeft whether the stack was on the left side of the screen when expanded.
+     * @param animate whether the pointer should animate to this position.
      */
     public void setPointerPosition(float bubblePosition, boolean onLeft, boolean animate) {
         // Pointer gets drawn in the padding
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index 8a120b9..97e5ee3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -579,11 +579,10 @@
 
         // Showing vertically: might need to translate the bubbles above the IME.
         // Subtract spacing here to provide a margin between top of IME and bottom of bubble row.
-        final float bottomInset = getImeHeight() + mInsets.bottom - (mSpacingBetweenBubbles * 2);
+        final float bottomHeight = getImeHeight() + mInsets.bottom - (mSpacingBetweenBubbles * 2);
+        final float bottomInset = mScreenRect.bottom - bottomHeight;
         final float expandedStackSize = getExpandedStackSize(numberOfBubbles);
-        final float centerPosition = showBubblesVertically()
-                ? mPositionRect.centerY()
-                : mPositionRect.centerX();
+        final float centerPosition = mPositionRect.centerY();
         final float rowBottom = centerPosition + (expandedStackSize / 2f);
         final float rowTop = centerPosition - (expandedStackSize / 2f);
         float rowTopForIme = rowTop;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index e4e5e3d..3319411 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1139,6 +1139,7 @@
         // The menu itself should respect locale direction so the icons are on the correct side.
         mManageMenu.setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
         addView(mManageMenu);
+        updateManageButtonListener();
     }
 
     /**
@@ -1315,7 +1316,6 @@
     /** Respond to the display size change by recalculating view size and location. */
     public void onDisplaySizeChanged() {
         updateOverflow();
-        setUpManageMenu();
         setUpFlyout();
         setUpDismissView();
         updateUserEdu();
@@ -1344,6 +1344,7 @@
         if (mIsExpanded) {
             updateExpandedView();
         }
+        setUpManageMenu();
     }
 
     @Override
@@ -2814,7 +2815,7 @@
                 // a race condition with adding the BubbleExpandedView view to the expanded view
                 // container. Due to the race condition the click handler sometimes is not set up
                 // correctly and is never called.
-                bev.setManageClickListener((view) -> showManageMenu(true /* show */));
+                updateManageButtonListener();
             }, 0);
 
             if (!mIsExpansionAnimating) {
@@ -2825,6 +2826,16 @@
         }
     }
 
+    private void updateManageButtonListener() {
+        if (mIsExpanded && mExpandedBubble != null
+                && mExpandedBubble.getExpandedView() != null) {
+            BubbleExpandedView bev = mExpandedBubble.getExpandedView();
+            bev.setManageClickListener((view) -> {
+                showManageMenu(true /* show */);
+            });
+        }
+    }
+
     /**
      * Requests a snapshot from the currently expanded bubble's TaskView and displays it in a
      * SurfaceView. This allows us to load a newly expanded bubble's Activity into the TaskView,
diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
index d541da0..b893b45 100644
--- a/mms/java/android/telephony/MmsManager.java
+++ b/mms/java/android/telephony/MmsManager.java
@@ -70,7 +70,8 @@
             }
 
             iMms.sendMessage(subId, ActivityThread.currentPackageName(), contentUri,
-                    locationUrl, configOverrides, sentIntent, messageId);
+                    locationUrl, configOverrides, sentIntent, messageId,
+                    mContext.getAttributionTag());
         } catch (RemoteException e) {
             // Ignore it
         }
@@ -102,7 +103,7 @@
             }
             iMms.downloadMessage(subId, ActivityThread.currentPackageName(),
                     locationUrl, contentUri, configOverrides, downloadedIntent,
-                    messageId);
+                    messageId, mContext.getAttributionTag());
         } catch (RemoteException e) {
             // Ignore it
         }
diff --git a/mms/java/com/android/internal/telephony/IMms.aidl b/mms/java/com/android/internal/telephony/IMms.aidl
index e0e0a4a..3cdde10 100644
--- a/mms/java/com/android/internal/telephony/IMms.aidl
+++ b/mms/java/com/android/internal/telephony/IMms.aidl
@@ -26,7 +26,7 @@
  */
 interface IMms {
     /**
-     * Send an MMS message
+     * Send an MMS message with attribution tag.
      *
      * @param subId the SIM id
      * @param callingPkg the package name of the calling app
@@ -38,10 +38,11 @@
      * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is successfully sent, or failed
      * @param messageId An id that uniquely identifies the message requested to be sent.
+     * @param attributionTag a tag that attributes the call to a client App.
      */
     void sendMessage(int subId, String callingPkg, in Uri contentUri,
             String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent,
-            in long messageId);
+            in long messageId, String attributionTag);
 
     /**
      * Download an MMS message using known location and transaction id
@@ -57,10 +58,11 @@
      * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is downloaded, or the download is failed
      * @param messageId An id that uniquely identifies the message requested to be downloaded.
+     * @param attributionTag a tag that attributes the call to a client App.
     */
     void downloadMessage(int subId, String callingPkg, String locationUrl,
             in Uri contentUri, in Bundle configOverrides,
-            in PendingIntent downloadedIntent, in long messageId);
+            in PendingIntent downloadedIntent, in long messageId, String attributionTag);
 
     /**
      * Import a text message into system's SMS store
diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
index c37054e..c0e6c09 100644
--- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
+++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml
@@ -12,120 +12,135 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/activity_confirmation"
-              style="@style/ContainerLayout">
-
-    <!-- A header for selfManaged devices only. -->
-    <include layout="@layout/vendor_header" />
-
-    <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
-
-    <ImageView
-        android:id="@+id/profile_icon"
+        android:id="@+id/activity_confirmation"
         android:layout_width="match_parent"
-        android:layout_height="32dp"
-        android:gravity="center"
-        android:layout_marginTop="18dp"
-        android:tint="@android:color/system_accent1_600"/>
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:minWidth="340dp">
 
-    <LinearLayout style="@style/Description">
-        <TextView
-            android:id="@+id/title"
-            style="@style/DescriptionTitle" />
+    <LinearLayout android:id="@+id/association_confirmation"
+                  style="@style/ContainerLayout">
 
-        <TextView
-            android:id="@+id/summary"
-            style="@style/DescriptionSummary" />
+        <!-- A header for selfManaged devices only. -->
+        <include layout="@layout/vendor_header" />
+
+        <!-- Do NOT change the ID of the root LinearLayout above: it's referenced in CTS tests. -->
+
+        <ImageView
+            android:id="@+id/profile_icon"
+            android:layout_width="match_parent"
+            android:layout_height="32dp"
+            android:gravity="center"
+            android:layout_marginTop="18dp"
+            android:tint="@android:color/system_accent1_600"/>
+
+        <LinearLayout style="@style/Description">
+            <TextView
+                android:id="@+id/title"
+                style="@style/DescriptionTitle" />
+
+            <TextView
+                android:id="@+id/summary"
+                style="@style/DescriptionSummary" />
+
+        </LinearLayout>
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+
+            <LinearLayout
+                android:id="@+id/multiple_device_list"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="12dp"
+                android:layout_marginBottom="12dp"
+                android:orientation="vertical"
+                android:visibility="gone">
+
+                <View
+                    android:id="@+id/border_top"
+                    style="@style/DeviceListBorder" />
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/device_list"
+                    android:layout_width="match_parent"
+                    android:scrollbars="vertical"
+                    android:layout_marginBottom="12dp"
+                    android:layout_height="200dp" />
+
+                <View
+                    android:id="@+id/border_bottom"
+                    style="@style/DeviceListBorder" />
+
+            </LinearLayout>
+
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/permission_list"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+            <ProgressBar
+                android:id="@+id/spinner_multiple_device"
+                android:visibility="gone"
+                style="@style/Spinner"  />
+
+        </RelativeLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:layout_marginTop="16dp">
+
+            <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
+
+            <Button
+                android:id="@+id/btn_positive"
+                style="@style/PositiveButton"
+                android:text="@string/consent_yes" />
+
+            <Button
+                android:id="@+id/btn_negative"
+                android:layout_marginBottom="12dp"
+                style="@style/NegativeButton"
+                android:text="@string/consent_no" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="bottom|right"
+            android:orientation="vertical"
+            android:layout_marginRight="16dp"
+            android:layout_marginBottom="16dp">
+
+            <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
+
+            <Button
+                android:id="@+id/btn_negative_multiple_devices"
+                style="@style/NegativeButtonMultipleDevices"
+                android:textColor="?android:textColorPrimary"
+                android:visibility="gone"
+                android:text="@string/consent_no" />
+        </LinearLayout>
 
     </LinearLayout>
 
     <RelativeLayout
         android:layout_width="match_parent"
-        android:layout_height="0dp"
+        android:layout_height="wrap_content"
         android:layout_weight="1">
 
-        <LinearLayout
-            android:id="@+id/multiple_device_list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="12dp"
-            android:layout_marginBottom="12dp"
-            android:orientation="vertical"
-            android:visibility="gone">
-
-            <View
-                android:id="@+id/border_top"
-                style="@style/DeviceListBorder" />
-
-            <androidx.recyclerview.widget.RecyclerView
-                android:id="@+id/device_list"
-                android:layout_width="match_parent"
-                android:scrollbars="vertical"
-                android:layout_marginBottom="12dp"
-                android:layout_height="200dp" />
-
-            <View
-                android:id="@+id/border_bottom"
-                style="@style/DeviceListBorder" />
-
-        </LinearLayout>
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/permission_list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
         <ProgressBar
-            android:id="@+id/spinner"
-            android:layout_width="56dp"
-            android:layout_height="56dp"
-            android:layout_centerInParent="true"
-            android:indeterminate="true"
-            android:tint="@android:color/system_accent1_600"
+            android:id="@+id/spinner_single_device"
             android:visibility="gone"
-            style="?android:attr/progressBarStyleLarge" />
-
-    </RelativeLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:orientation="vertical"
-        android:layout_marginTop="16dp">
-
-        <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
-
-        <Button
-            android:id="@+id/btn_positive"
-            style="@style/PositiveButton"
-            android:text="@string/consent_yes" />
-
-        <Button
-            android:id="@+id/btn_negative"
-            android:layout_marginBottom="12dp"
-            style="@style/NegativeButton"
-            android:text="@string/consent_no" />
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="bottom|right"
-        android:orientation="vertical"
-        android:layout_marginRight="16dp"
-        android:layout_marginBottom="16dp">
-
-        <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. -->
-
-        <Button
-            android:id="@+id/btn_negative_multiple_devices"
-            style="@style/NegativeButtonMultipleDevices"
-            android:textColor="?android:textColorPrimary"
-            android:visibility="gone"
-            android:text="@string/consent_no" />
-    </LinearLayout>
+            style="@style/Spinner" />
+    </RelativeLayout>>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml
index faa3032..c38323f 100644
--- a/packages/CompanionDeviceManager/res/values/styles.xml
+++ b/packages/CompanionDeviceManager/res/values/styles.xml
@@ -108,4 +108,11 @@
         <item name="android:background">@android:color/system_accent1_300</item>
     </style>
 
+    <style name="Spinner"
+           parent="@android:style/Widget.Material.Light.ProgressBar.Large">
+        <item name="android:layout_width">56dp</item>
+        <item name="android:layout_height">56dp</item>
+        <item name="android:indeterminate">true</item>
+        <item name="android:layout_centerInParent">true</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index b596816..37cbf30 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -122,7 +122,10 @@
 
     // Progress indicator is only shown while we are looking for the first suitable device for a
     // multiple device association.
-    private ProgressBar mProgressIndicator;
+    private ProgressBar mMultipleDeviceSpinner;
+    // Progress indicator is only shown while we are looking for the first suitable device for a
+    // single device association.
+    private ProgressBar mSingleDeviceSpinner;
 
     // Present for self-managed association requests and "single-device" regular association
     // regular.
@@ -255,7 +258,7 @@
         setContentView(R.layout.activity_confirmation);
 
         mMultipleDeviceList = findViewById(R.id.multiple_device_list);
-        mAssociationConfirmationDialog = findViewById(R.id.activity_confirmation);
+        mAssociationConfirmationDialog = findViewById(R.id.association_confirmation);
         mVendorHeader = findViewById(R.id.vendor_header);
 
         mTitle = findViewById(R.id.title);
@@ -269,7 +272,8 @@
 
         mDeviceListRecyclerView = findViewById(R.id.device_list);
 
-        mProgressIndicator = findViewById(R.id.spinner);
+        mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device);
+        mSingleDeviceSpinner = findViewById(R.id.spinner_single_device);
         mDeviceAdapter = new DeviceListAdapter(this, this::onListItemClick);
 
         mPermissionListRecyclerView = findViewById(R.id.permission_list);
@@ -468,8 +472,10 @@
                 deviceFilterPairs -> updateSingleDeviceUi(
                         deviceFilterPairs, deviceProfile, appLabel));
 
+        mSingleDeviceSpinner.setVisibility(View.VISIBLE);
         mPermissionListRecyclerView.setVisibility(View.GONE);
         mDeviceListRecyclerView.setVisibility(View.GONE);
+        mAssociationConfirmationDialog.setVisibility(View.GONE);
     }
 
     private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs,
@@ -499,6 +505,8 @@
         mTitle.setText(title);
         mSummary.setText(summary);
         mProfileIcon.setImageDrawable(profileIcon);
+        mSingleDeviceSpinner.setVisibility(View.GONE);
+        mAssociationConfirmationDialog.setVisibility(View.VISIBLE);
     }
 
     private void initUiForMultipleDevices(CharSequence appLabel) {
@@ -535,7 +543,7 @@
                 deviceFilterPairs -> {
                     // Dismiss the progress bar once there's one device found for multiple devices.
                     if (deviceFilterPairs.size() >= 1) {
-                        mProgressIndicator.setVisibility(View.GONE);
+                        mMultipleDeviceSpinner.setVisibility(View.GONE);
                     }
 
                     mDeviceAdapter.setDevices(deviceFilterPairs);
@@ -546,7 +554,7 @@
         mButtonNotAllow.setVisibility(View.GONE);
         mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE);
         mMultipleDeviceList.setVisibility(View.VISIBLE);
-        mProgressIndicator.setVisibility(View.VISIBLE);
+        mMultipleDeviceSpinner.setVisibility(View.VISIBLE);
     }
 
     private void onListItemClick(int position) {
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 74fe4bd..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ /dev/null
@@ -1,744 +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.annotation.Nullable;
-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. If null, the method does
-     *                  nothing and returning false.
-     * @return true if successfully filled the bucket, false otherwise.
-     */
-    public boolean getNextBucket(@Nullable 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(@Nullable 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(@Nullable 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 f41475b..0000000
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ /dev/null
@@ -1,1238 +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, @Nullable 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, @Nullable 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, @Nullable 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)
-     */
-    @NonNull
-    @WorkerThread
-    public NetworkStats queryDetailsForUid(int networkType, @Nullable 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 */
-    @NonNull
-    public NetworkStats queryDetailsForUid(@NonNull 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.
-     * 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.
-     * @return Statistics which is described above.
-     * @throws SecurityException if permissions are insufficient to read network statistics.
-     */
-    @NonNull
-    @WorkerThread
-    public NetworkStats queryDetailsForUidTag(int networkType, @Nullable 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 which is described above.
-     * @throws SecurityException if permissions are insufficient to read network statistics.
-     */
-    @NonNull
-    @WorkerThread
-    public NetworkStats queryDetailsForUidTagState(int networkType, @Nullable 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, @Nullable 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(client = MODULE_LIBRARIES)
-    @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(client = MODULE_LIBRARIES)
-    @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.
-     *
-     * <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.
-     */
-    public void registerUsageCallback(int networkType, @Nullable String subscriberId,
-            long thresholdBytes, @NonNull 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, @Nullable String subscriberId,
-            long thresholdBytes, @NonNull 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(@NonNull 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, @Nullable 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})
-    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})
-    public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
-        try {
-            provider.getProviderCallbackBinderOrThrow().unregister();
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
-    }
-
-    private static NetworkTemplate createTemplate(int networkType, @Nullable 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 f0ff465..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, android.net.NetworkTemplate.class);
-                    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 03bb187..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(), android.net.Network.class);
-        mSpiResourceId = in.readInt();
-        mEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
-        mAuthentication =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
-        mAuthenticatedEncryption =
-                (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
-        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 390af82..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.os.ParcelFileDescriptor.class);
-    }
-
-    @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 c018e91..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, android.net.Network.class);
-        mNetworkCapabilities = in.readParcelable(null, android.net.NetworkCapabilities.class);
-        mLinkProperties = in.readParcelable(null, android.net.LinkProperties.class);
-        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 bcfeab9..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ /dev/null
@@ -1,1860 +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 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. */
-    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.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getUid() {
-            return uid;
-        }
-
-        /**
-         * @return the set state of this entry.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        @State public int getSet() {
-            return set;
-        }
-
-        /**
-         * @return the tag value of this entry.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getTag() {
-            return tag;
-        }
-
-        /**
-         * @return the metered state.
-         * @hide
-         */
-        @Meteredness
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getMetered() {
-            return metered;
-        }
-
-        /**
-         * @return the roaming state.
-         * @hide
-         */
-        @Roaming
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getRoaming() {
-            return roaming;
-        }
-
-        /**
-         * @return the default network state.
-         * @hide
-         */
-        @DefaultNetwork
-        @SystemApi(client = MODULE_LIBRARIES)
-        public int getDefaultNetwork() {
-            return defaultNetwork;
-        }
-
-        /**
-         * @return the number of received bytes.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public long getRxBytes() {
-            return rxBytes;
-        }
-
-        /**
-         * @return the number of received packets.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public long getRxPackets() {
-            return rxPackets;
-        }
-
-        /**
-         * @return the number of transmitted bytes.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public long getTxBytes() {
-            return txBytes;
-        }
-
-        /**
-         * @return the number of transmitted packets.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        public long getTxPackets() {
-            return txPackets;
-        }
-
-        /**
-         * @return the count of network operations performed for this entry.
-         * @hide
-         */
-        @SystemApi(client = MODULE_LIBRARIES)
-        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(client = MODULE_LIBRARIES)
-    @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 dc4ac55..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 = 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(client = MODULE_LIBRARIES)
-    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(@NonNull 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(@NonNull 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(@NonNull DatagramSocket socket) throws SocketException {
-        SocketTagger.get().tag(socket);
-    }
-
-    /**
-     * Remove any statistics parameters from the given {@link DatagramSocket}.
-     */
-    public static void untagDatagramSocket(@NonNull 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(@NonNull FileDescriptor fd) throws IOException {
-        SocketTagger.get().tag(fd);
-    }
-
-    /**
-     * Remove any statistics parameters from the given {@link FileDescriptor}
-     * socket.
-     */
-    public static void untagFileDescriptor(@NonNull 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 7ab53b1..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*/, java.lang.String.class);
-        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/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/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index 18a3b37..c0436b2 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -18,6 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:theme="@style/FloatingOverlay"
     android:alpha="0"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
@@ -29,7 +30,6 @@
         android:src="@drawable/overlay_actions_background_protection"/>
     <com.android.systemui.screenshot.DraggableConstraintLayout
         android:id="@+id/clipboard_ui"
-        android:theme="@style/FloatingOverlay"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
         <ImageView
diff --git a/packages/SystemUI/res/layout/rounded_corners_bottom.xml b/packages/SystemUI/res/layout/rounded_corners_bottom.xml
new file mode 100644
index 0000000..bb6d4bd
--- /dev/null
+++ b/packages/SystemUI/res/layout/rounded_corners_bottom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 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.
+-->
+<com.android.systemui.RegionInterceptingFrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rounded_corners_bottom"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <ImageView
+        android:id="@+id/left"
+        android:layout_width="12dp"
+        android:layout_height="12dp"
+        android:layout_gravity="left|bottom"
+        android:tint="#ff000000"
+        android:visibility="gone"
+        android:src="@drawable/rounded_corner_bottom"/>
+
+    <ImageView
+        android:id="@+id/right"
+        android:layout_width="12dp"
+        android:layout_height="12dp"
+        android:tint="#ff000000"
+        android:visibility="gone"
+        android:layout_gravity="right|bottom"
+        android:src="@drawable/rounded_corner_bottom"/>
+
+</com.android.systemui.RegionInterceptingFrameLayout>
diff --git a/packages/SystemUI/res/layout/rounded_corners_top.xml b/packages/SystemUI/res/layout/rounded_corners_top.xml
new file mode 100644
index 0000000..46648c8
--- /dev/null
+++ b/packages/SystemUI/res/layout/rounded_corners_top.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 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.
+-->
+<com.android.systemui.RegionInterceptingFrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rounded_corners_top"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <ImageView
+        android:id="@+id/left"
+        android:layout_width="12dp"
+        android:layout_height="12dp"
+        android:layout_gravity="left|top"
+        android:tint="#ff000000"
+        android:visibility="gone"
+        android:src="@drawable/rounded_corner_top"/>
+
+    <ImageView
+        android:id="@+id/right"
+        android:layout_width="12dp"
+        android:layout_height="12dp"
+        android:tint="#ff000000"
+        android:visibility="gone"
+        android:layout_gravity="right|top"
+        android:src="@drawable/rounded_corner_top"/>
+
+</com.android.systemui.RegionInterceptingFrameLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 49fc848..50fdc7b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -138,7 +138,8 @@
     <color name="udfps_enroll_icon">#7DA7F1</color>
     <color name="udfps_moving_target_fill">#475670</color>
     <color name="udfps_enroll_progress">#7DA7F1</color>
-    <color name="udfps_enroll_progress_help">#ffEE675C</color>
+    <color name="udfps_enroll_progress_help">#607DA7F1</color>
+    <color name="udfps_enroll_progress_help_with_talkback">#ffEE675C</color>
 
     <!-- Floating overlay actions -->
     <color name="overlay_button_ripple">#1f000000</color>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 096b9a0..926734c 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -167,11 +167,5 @@
     <item type="id" name="action_move_bottom_right"/>
     <item type="id" name="action_move_to_edge_and_hide"/>
     <item type="id" name="action_move_out_edge_and_show"/>
-
-    <!-- rounded corner view id -->
-    <item type="id" name="rounded_corner_top_left"/>
-    <item type="id" name="rounded_corner_top_right"/>
-    <item type="id" name="rounded_corner_bottom_left"/>
-    <item type="id" name="rounded_corner_bottom_right"/>
 </resources>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
index 15593ea..9e5aeb8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.unfold
 
+import android.app.ActivityManager
 import android.content.ContentResolver
 import android.content.Context
 import android.hardware.SensorManager
@@ -51,6 +52,7 @@
             @BindsInstance config: UnfoldTransitionConfig,
             @BindsInstance screenStatusProvider: ScreenStatusProvider,
             @BindsInstance deviceStateManager: DeviceStateManager,
+            @BindsInstance activityManager: ActivityManager,
             @BindsInstance sensorManager: SensorManager,
             @BindsInstance @Main handler: Handler,
             @BindsInstance @Main executor: Executor,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index 8e4ff9b..cc56007c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -17,6 +17,7 @@
 
 package com.android.systemui.unfold
 
+import android.app.ActivityManager
 import android.content.Context
 import android.hardware.SensorManager
 import android.hardware.devicestate.DeviceStateManager
@@ -39,6 +40,7 @@
     config: UnfoldTransitionConfig,
     screenStatusProvider: ScreenStatusProvider,
     deviceStateManager: DeviceStateManager,
+    activityManager: ActivityManager,
     sensorManager: SensorManager,
     mainHandler: Handler,
     mainExecutor: Executor,
@@ -51,6 +53,7 @@
             config,
             screenStatusProvider,
             deviceStateManager,
+            activityManager,
             sensorManager,
             mainHandler,
             mainExecutor,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 5266f09..3daae75 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -33,7 +33,7 @@
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
 
 /** Maps fold updates to unfold transition progress using DynamicAnimation. */
-internal class PhysicsBasedUnfoldTransitionProgressProvider(
+class PhysicsBasedUnfoldTransitionProgressProvider(
     private val foldStateProvider: FoldStateProvider
 ) : UnfoldTransitionProgressProvider, FoldUpdatesListener, DynamicAnimation.OnAnimationEndListener {
 
@@ -97,7 +97,17 @@
             FOLD_UPDATE_START_CLOSING -> {
                 // The transition might be already running as the device might start closing several
                 // times before reaching an end state.
-                if (!isTransitionRunning) {
+                if (isTransitionRunning) {
+                    // If we are cancelling the animation, reset that so we can resume it normally.
+                    // The animation could be 'cancelled' when the user stops folding/unfolding
+                    // for some period of time or fully unfolds the device. In this case,
+                    // it is forced to run to the end ignoring all further hinge angle events.
+                    // By resetting this flag we allow reacting to hinge angle events again, so
+                    // the transition continues running.
+                    if (isAnimatedCancelRunning) {
+                        isAnimatedCancelRunning = false
+                    }
+                } else {
                     startTransition(startValue = 1f)
                 }
             }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 24ecf87..eb1181d9 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -16,6 +16,8 @@
 package com.android.systemui.unfold.updates
 
 import android.annotation.FloatRange
+import android.app.ActivityManager
+import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
 import android.content.Context
 import android.hardware.devicestate.DeviceStateManager
 import android.os.Handler
@@ -39,6 +41,7 @@
     private val hingeAngleProvider: HingeAngleProvider,
     private val screenStatusProvider: ScreenStatusProvider,
     private val deviceStateManager: DeviceStateManager,
+    private val activityManager: ActivityManager,
     @Main private val mainExecutor: Executor,
     @Main private val handler: Handler
 ) : FoldStateProvider {
@@ -92,10 +95,12 @@
         }
 
         val isClosing = angle < lastHingeAngle
+        val closingThreshold = getClosingThreshold()
+        val closingThresholdMet = closingThreshold == null || angle < closingThreshold
         val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
         val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
 
-        if (isClosing && !closingEventDispatched && !isFullyOpened) {
+        if (isClosing && closingThresholdMet && !closingEventDispatched && !isFullyOpened) {
             notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
         }
 
@@ -113,6 +118,33 @@
         outputListeners.forEach { it.onHingeAngleUpdate(angle) }
     }
 
+    /**
+     * Fold animation should be started only after the threshold returned here.
+     *
+     * This has been introduced because the fold animation might be distracting/unwanted on top of
+     * apps that support table-top/HALF_FOLDED mode. Only for launcher, there is no threshold.
+     */
+    private fun getClosingThreshold(): Int? {
+        val activityType =
+            activityManager
+                .getRunningTasks(/* maxNum= */ 1)
+                ?.getOrNull(0)
+                ?.configuration
+                ?.windowConfiguration
+                ?.activityType
+                ?: return null
+
+        if (DEBUG) {
+            Log.d(TAG, "activityType=" + activityType)
+        }
+
+        return if (activityType == ACTIVITY_TYPE_HOME) {
+            null
+        } else {
+            START_CLOSING_ON_APPS_THRESHOLD_DEGREES
+        }
+    }
+
     private inner class FoldStateListener(context: Context) :
         DeviceStateManager.FoldStateListener(
             context,
@@ -199,7 +231,10 @@
  * Time after which [FOLD_UPDATE_FINISH_HALF_OPEN] is emitted following a
  * [FOLD_UPDATE_START_CLOSING] or [FOLD_UPDATE_START_OPENING] event, if an end state is not reached.
  */
-@VisibleForTesting const val HALF_OPENED_TIMEOUT_MILLIS = 1000L
+@VisibleForTesting const val HALF_OPENED_TIMEOUT_MILLIS = 600L
 
 /** Threshold after which we consider the device fully unfolded. */
 @VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
+
+/** Fold animation on top of apps only when the angle exceeds this threshold. */
+@VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 0118813..22c6937 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -369,15 +369,10 @@
      * Update the rounded corner size.
      */
     fun updateRoundedCornerSize(top: Int, bottom: Int) {
-        if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) {
-            return
-        }
         roundedCornerTopSize = top
         roundedCornerBottomSize = bottom
         updateRoundedCornerDrawableBounds()
-
-        // Use requestLayout() to trigger transparent region recalculated
-        requestLayout()
+        invalidate()
     }
 
     private fun updateRoundedCornerDrawableBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 5de09b1..2f5292c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -77,7 +77,6 @@
 import com.android.systemui.decor.DecorProviderKt;
 import com.android.systemui.decor.OverlayWindow;
 import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
-import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
 import com.android.systemui.decor.RoundedCornerResDelegate;
 import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.settings.UserTracker;
@@ -139,9 +138,6 @@
     @VisibleForTesting
     protected RoundedCornerResDelegate mRoundedCornerResDelegate;
     @VisibleForTesting
-    protected DecorProviderFactory mRoundedCornerFactory;
-    private int mProviderRefreshToken = 0;
-    @VisibleForTesting
     protected OverlayWindow[] mOverlays = null;
     @Nullable
     private DisplayCutoutView[] mCutoutViews;
@@ -296,11 +292,11 @@
         mDisplayUniqueId = mContext.getDisplay().getUniqueId();
         mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
                 mDisplayUniqueId);
-        mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
         mWindowManager = mContext.getSystemService(WindowManager.class);
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
-        updateHwLayerRoundedCornerDrawable();
+        updateRoundedCornerDrawable();
+        updateRoundedCornerRadii();
         setupDecorations();
         setupCameraListener();
 
@@ -352,7 +348,7 @@
                 final String newUniqueId = mContext.getDisplay().getUniqueId();
                 if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
                     mDisplayUniqueId = newUniqueId;
-                    mRoundedCornerResDelegate.updateDisplayUniqueId(newUniqueId, null);
+                    mRoundedCornerResDelegate.reloadAll(newUniqueId);
                     final DisplayDecorationSupport newScreenDecorationSupport =
                             mContext.getDisplay().getDisplayDecorationSupport();
                     // When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
@@ -363,12 +359,12 @@
                         setupDecorations();
                         return;
                     }
-                    updateHwLayerRoundedCornerDrawable();
+                    updateRoundedCornerDrawable();
                 }
                 if (mScreenDecorHwcLayer != null) {
                     mScreenDecorHwcLayer.onDisplayChanged(displayId);
                 }
-                updateView();
+                updateOrientation();
             }
         };
 
@@ -410,22 +406,22 @@
     }
 
     private void setupDecorations() {
-        if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) {
-            List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders());
+        List<DecorProvider> decorProviders = mDotFactory.getProviders();
+
+        if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) {
             if (mHwcScreenDecorationSupport != null) {
                 createHwcOverlay();
             } else {
                 removeHwcOverlay();
-                decorProviders.addAll(mRoundedCornerFactory.getProviders());
             }
             final DisplayCutout cutout = getCutout();
             for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
-                if (shouldShowSwLayerCutout(i, cutout) || shouldShowSwLayerRoundedCorner(i, cutout)
-                        || shouldShowSwLayerPrivacyDot(i, cutout)) {
+                if (shouldShowCutout(i, cutout) || shouldShowRoundedCorner(i, cutout)
+                        || shouldShowPrivacyDot(i, cutout)) {
                     Pair<List<DecorProvider>, List<DecorProvider>> pair =
                             DecorProviderKt.partitionAlignedBound(decorProviders, i);
                     decorProviders = pair.getSecond();
-                    createOverlay(i, pair.getFirst());
+                    createOverlay(i, cutout, pair.getFirst());
                 } else {
                     removeOverlay(i);
                 }
@@ -526,6 +522,7 @@
 
     private void createOverlay(
             @BoundsPosition int pos,
+            @Nullable DisplayCutout cutout,
             @NonNull List<DecorProvider> decorProviders) {
         if (mOverlays == null) {
             mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH];
@@ -550,7 +547,7 @@
             mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
             mCutoutViews[pos].setColor(mTintColor);
             overlayView.addView(mCutoutViews[pos]);
-            mCutoutViews[pos].updateRotation(mRotation);
+            updateView(pos, cutout);
         }
 
         mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
@@ -606,7 +603,7 @@
     private OverlayWindow overlayForPosition(
             @BoundsPosition int pos,
             @NonNull List<DecorProvider> decorProviders) {
-        final OverlayWindow currentOverlay = new OverlayWindow(mContext);
+        final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos);
         decorProviders.forEach(provider -> {
             removeOverlayView(provider.getViewId());
             currentOverlay.addDecorProvider(provider, mRotation);
@@ -620,16 +617,22 @@
         return currentOverlay;
     }
 
-    private void updateView() {
-        if (mOverlays == null) {
+    private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
+        if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) {
             return;
         }
-        ++mProviderRefreshToken;
-        for (final OverlayWindow overlay: mOverlays) {
-            if (overlay == null) {
-                continue;
-            }
-            overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
+
+        // update rounded corner view rotation
+        updateRoundedCornerView(pos, R.id.left, cutout);
+        updateRoundedCornerView(pos, R.id.right, cutout);
+        updateRoundedCornerSize(
+                mRoundedCornerResDelegate.getTopRoundedSize(),
+                mRoundedCornerResDelegate.getBottomRoundedSize());
+        updateRoundedCornerImageView();
+
+        // update cutout view rotation
+        if (mCutoutViews != null && mCutoutViews[pos] != null) {
+            mCutoutViews[pos].updateRotation(mRotation);
         }
     }
 
@@ -803,6 +806,7 @@
             int oldRotation = mRotation;
             mPendingRotationChange = false;
             updateOrientation();
+            updateRoundedCornerRadii();
             if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
             setupDecorations();
             if (mOverlays != null) {
@@ -862,32 +866,109 @@
             mDotViewController.setNewRotation(newRotation);
         }
 
-        if (!mPendingRotationChange && newRotation != mRotation) {
+        if (mPendingRotationChange) {
+            return;
+        }
+        if (newRotation != mRotation) {
             mRotation = newRotation;
             if (mScreenDecorHwcLayer != null) {
                 mScreenDecorHwcLayer.pendingRotationChange = false;
                 mScreenDecorHwcLayer.updateRotation(mRotation);
-                updateHwLayerRoundedCornerSize();
-                updateHwLayerRoundedCornerDrawable();
             }
-            updateLayoutParams();
-            // update cutout view rotation
-            if (mCutoutViews != null) {
-                for (final DisplayCutoutView cutoutView: mCutoutViews) {
-                    if (cutoutView == null) {
+            if (mOverlays != null) {
+                updateLayoutParams();
+                final DisplayCutout cutout = getCutout();
+                for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+                    if (mOverlays[i] == null) {
                         continue;
                     }
-                    cutoutView.updateRotation(mRotation);
+                    updateView(i, cutout);
                 }
             }
         }
-
-        // update views
-        updateView();
     }
 
+    private void updateRoundedCornerRadii() {
+        // We should eventually move to just using the intrinsic size of the drawables since
+        // they should be sized to the exact pixels they want to cover. Therefore I'm purposely not
+        // upgrading all of the configs to contain (width, height) pairs. Instead assume that a
+        // device configured using the single integer config value is okay with drawing the corners
+        // as a square
+        final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
+        final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
+        mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
+        final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
+        final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
+
+        if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth()
+                || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) {
+            onTuningChanged(SIZE, null);
+        }
+    }
+
+    private void updateRoundedCornerView(@BoundsPosition int pos, int id,
+            @Nullable DisplayCutout cutout) {
+        final View rounded = mOverlays[pos].getRootView().findViewById(id);
+        if (rounded == null) {
+            return;
+        }
+        rounded.setVisibility(View.GONE);
+        if (shouldShowRoundedCorner(pos, cutout)) {
+            final int gravity = getRoundedCornerGravity(pos, id == R.id.left);
+            ((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity;
+            setRoundedCornerOrientation(rounded, gravity);
+            rounded.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private int getRoundedCornerGravity(@BoundsPosition int pos, boolean isStart) {
+        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
+        switch (rotatedPos) {
+            case BOUNDS_POSITION_LEFT:
+                return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.BOTTOM | Gravity.LEFT;
+            case BOUNDS_POSITION_TOP:
+                return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT;
+            case BOUNDS_POSITION_RIGHT:
+                return isStart ? Gravity.TOP | Gravity.RIGHT : Gravity.BOTTOM | Gravity.RIGHT;
+            case BOUNDS_POSITION_BOTTOM:
+                return isStart ? Gravity.BOTTOM | Gravity.LEFT : Gravity.BOTTOM | Gravity.RIGHT;
+            default:
+                throw new IllegalArgumentException("Incorrect position: " + rotatedPos);
+        }
+    }
+
+    /**
+     * Configures the rounded corner drawable's view matrix based on the gravity.
+     *
+     * The gravity describes which corner to configure for, and the drawable we are rotating is
+     * assumed to be oriented for the top-left corner of the device regardless of the target corner.
+     * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
+     * y-axis for the top-right and bottom-left corners.
+     */
+    private void setRoundedCornerOrientation(View corner, int gravity) {
+        corner.setRotation(0);
+        corner.setScaleX(1);
+        corner.setScaleY(1);
+        switch (gravity) {
+            case Gravity.TOP | Gravity.LEFT:
+                return;
+            case Gravity.TOP | Gravity.RIGHT:
+                corner.setScaleX(-1); // flip X axis
+                return;
+            case Gravity.BOTTOM | Gravity.LEFT:
+                corner.setScaleY(-1); // flip Y axis
+                return;
+            case Gravity.BOTTOM | Gravity.RIGHT:
+                corner.setRotation(180);
+                return;
+            default:
+                throw new IllegalArgumentException("Unsupported gravity: " + gravity);
+        }
+    }
     private boolean hasRoundedCorners() {
-        return mRoundedCornerFactory.getHasProviders();
+        return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
+                || mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
+                || mRoundedCornerResDelegate.isMultipleRadius();
     }
 
     private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
@@ -906,19 +987,17 @@
         }
     }
 
-    private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
+    private boolean shouldShowRoundedCorner(@BoundsPosition int pos,
             @Nullable DisplayCutout cutout) {
         return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
                 && mHwcScreenDecorationSupport == null;
     }
 
-    private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
+    private boolean shouldShowPrivacyDot(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
         return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
     }
 
-    private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
-            @Nullable DisplayCutout cutout) {
+    private boolean shouldShowCutout(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
         final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
         final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
         return (bounds != null && !bounds[rotatedPos].isEmpty()
@@ -953,33 +1032,54 @@
             return;
         }
         mExecutor.execute(() -> {
-            if (mOverlays == null || !SIZE.equals(key)) {
-                return;
-            }
-            ++mProviderRefreshToken;
-            try {
-                final int sizeFactor = Integer.parseInt(newValue);
-                mRoundedCornerResDelegate.updateTuningSizeFactor(sizeFactor, mProviderRefreshToken);
-            } catch (NumberFormatException e) {
-                mRoundedCornerResDelegate.updateTuningSizeFactor(null, mProviderRefreshToken);
-            }
-            Integer[] filterIds = {
-                    R.id.rounded_corner_top_left,
-                    R.id.rounded_corner_top_right,
-                    R.id.rounded_corner_bottom_left,
-                    R.id.rounded_corner_bottom_right
-            };
-            for (final OverlayWindow overlay: mOverlays) {
-                if (overlay == null) {
-                    continue;
+            if (mOverlays == null) return;
+            if (SIZE.equals(key)) {
+                if (newValue != null) {
+                    try {
+                        mRoundedCornerResDelegate.updateTuningSizeFactor(
+                                Integer.parseInt(newValue));
+                    } catch (Exception e) {
+                    }
                 }
-                overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
-                        mDisplayUniqueId);
+                updateRoundedCornerSize(
+                        mRoundedCornerResDelegate.getTopRoundedSize(),
+                        mRoundedCornerResDelegate.getBottomRoundedSize());
             }
-            updateHwLayerRoundedCornerSize();
         });
     }
 
+    private void updateRoundedCornerDrawable() {
+        mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
+        updateRoundedCornerImageView();
+    }
+
+    private void updateRoundedCornerImageView() {
+        final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable();
+        final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable();
+
+        if (mScreenDecorHwcLayer != null) {
+            mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom);
+            return;
+        }
+
+        if (mOverlays == null) {
+            return;
+        }
+        final ColorStateList colorStateList = ColorStateList.valueOf(mTintColor);
+        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+            if (mOverlays[i] == null) {
+                continue;
+            }
+            final ViewGroup overlayView = mOverlays[i].getRootView();
+            ((ImageView) overlayView.findViewById(R.id.left)).setImageTintList(colorStateList);
+            ((ImageView) overlayView.findViewById(R.id.right)).setImageTintList(colorStateList);
+            ((ImageView) overlayView.findViewById(R.id.left)).setImageDrawable(
+                    isTopRoundedCorner(i, R.id.left) ? top : bottom);
+            ((ImageView) overlayView.findViewById(R.id.right)).setImageDrawable(
+                    isTopRoundedCorner(i, R.id.right) ? top : bottom);
+        }
+    }
+
     private void updateHwLayerRoundedCornerDrawable() {
         if (mScreenDecorHwcLayer == null) {
             return;
@@ -994,6 +1094,25 @@
         mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
     }
 
+    @VisibleForTesting
+    boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
+        switch (pos) {
+            case BOUNDS_POSITION_LEFT:
+            case BOUNDS_POSITION_RIGHT:
+                if (mRotation == ROTATION_270) {
+                    return id == R.id.left ? false : true;
+                } else {
+                    return id == R.id.left ? true : false;
+                }
+            case BOUNDS_POSITION_TOP:
+                return true;
+            case BOUNDS_POSITION_BOTTOM:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown bounds position");
+        }
+    }
+
     private void updateHwLayerRoundedCornerSize() {
         if (mScreenDecorHwcLayer == null) {
             return;
@@ -1005,6 +1124,28 @@
         mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
     }
 
+    private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) {
+
+        if (mScreenDecorHwcLayer != null) {
+            mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth());
+            return;
+        }
+
+        if (mOverlays == null) {
+            return;
+        }
+        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+            if (mOverlays[i] == null) {
+                continue;
+            }
+            final ViewGroup overlayView = mOverlays[i].getRootView();
+            setSize(overlayView.findViewById(R.id.left),
+                    isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom);
+            setSize(overlayView.findViewById(R.id.right),
+                    isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom);
+        }
+    }
+
     @VisibleForTesting
     protected void setSize(View view, Size pixelSize) {
         LayoutParams params = view.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
index 4c00735..085bcfa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
@@ -33,6 +33,8 @@
 import android.hardware.fingerprint.ISidefpsController
 import android.os.Handler
 import android.util.Log
+import android.view.View.AccessibilityDelegate
+import android.view.accessibility.AccessibilityEvent
 import android.view.Display
 import android.view.Gravity
 import android.view.LayoutInflater
@@ -181,6 +183,23 @@
         }
         lottie.addOverlayDynamicColor(context)
 
+        /**
+         * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from
+         * speaking @string/accessibility_fingerprint_label twice when sensor location indicator
+         * is in focus
+         */
+        view.setAccessibilityDelegate(object : AccessibilityDelegate() {
+            override fun dispatchPopulateAccessibilityEvent(
+                host: View,
+                event: AccessibilityEvent
+            ): Boolean {
+                return if (event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+                    true
+                } else {
+                    super.dispatchPopulateAccessibilityEvent(host, event)
+                }
+            }
+        })
         return view
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
index 631a461..f3a603f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
@@ -22,6 +22,7 @@
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Interpolator;
 import android.view.animation.OvershootInterpolator;
 
@@ -71,7 +72,13 @@
     public UdfpsEnrollProgressBarDrawable(@NonNull Context context) {
         mStrokeWidthPx = Utils.dpToPixels(context, STROKE_WIDTH_DP);
         mProgressColor = context.getColor(R.color.udfps_enroll_progress);
-        mHelpColor = context.getColor(R.color.udfps_enroll_progress_help);
+        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        final boolean isAccessbilityEnabled = am.isTouchExplorationEnabled();
+        if (!isAccessbilityEnabled) {
+            mHelpColor = context.getColor(R.color.udfps_enroll_progress_help);
+        } else {
+            mHelpColor = context.getColor(R.color.udfps_enroll_progress_help_with_talkback);
+        }
         mCheckmarkDrawable = context.getDrawable(R.drawable.udfps_enroll_checkmark);
         mCheckmarkDrawable.mutate();
         mCheckmarkInterpolator = new OvershootInterpolator();
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index 1b52bb6..804576a 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -247,7 +247,10 @@
                 SELF_PERMISSION, null);
         monitorOutsideTouches();
 
-        mContext.sendBroadcast(new Intent(COPY_OVERLAY_ACTION), SELF_PERMISSION);
+        Intent copyIntent = new Intent(COPY_OVERLAY_ACTION);
+        // Set package name so the system knows it's safe
+        copyIntent.setPackage(mContext.getPackageName());
+        mContext.sendBroadcast(copyIntent, SELF_PERMISSION);
     }
 
     void setClipData(ClipData clipData, String clipSource) {
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index 03ee8b1..3543bb4 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -15,8 +15,8 @@
  */
 
 package com.android.systemui.decor
-import android.content.Context
 import android.view.DisplayCutout
+import android.view.LayoutInflater
 import android.view.Surface
 import android.view.View
 import android.view.ViewGroup
@@ -38,20 +38,9 @@
     /** The aligned bounds for the view which is created through inflateView() */
     abstract val alignedBounds: List<Int>
 
-    /**
-     * Called when res info changed.
-     * Child provider needs to implement it if its view needs to be updated.
-     */
-    abstract fun onReloadResAndMeasure(
-        view: View,
-        reloadToken: Int,
-        @Surface.Rotation rotation: Int,
-        displayUniqueId: String? = null
-    )
-
     /** Inflate view into parent as current rotation */
     abstract fun inflateView(
-        context: Context,
+        inflater: LayoutInflater,
         parent: ViewGroup,
         @Surface.Rotation rotation: Int
     ): View
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index f38ff14..9f8679c 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -16,22 +16,31 @@
 package com.android.systemui.decor
 
 import android.annotation.IdRes
-import android.content.Context
+import android.view.DisplayCutout
+import android.view.LayoutInflater
 import android.view.Surface
 import android.view.View
 import android.view.ViewGroup
-import com.android.systemui.RegionInterceptingFrameLayout
+import com.android.systemui.R
+import java.util.HashMap
 
-class OverlayWindow(private val context: Context) {
+class OverlayWindow(private val layoutInflater: LayoutInflater, private val pos: Int) {
 
-    val rootView = RegionInterceptingFrameLayout(context) as ViewGroup
-    private val viewProviderMap = mutableMapOf<Int, Pair<View, DecorProvider>>()
+    private val layoutId: Int
+    get() {
+        return if (pos == DisplayCutout.BOUNDS_POSITION_LEFT ||
+                pos == DisplayCutout.BOUNDS_POSITION_TOP) {
+            R.layout.rounded_corners_top
+        } else {
+            R.layout.rounded_corners_bottom
+        }
+    }
 
-    fun addDecorProvider(
-        decorProvider: DecorProvider,
-        @Surface.Rotation rotation: Int
-    ) {
-        val view = decorProvider.inflateView(context, rootView, rotation)
+    val rootView = layoutInflater.inflate(layoutId, null) as ViewGroup
+    private val viewProviderMap: MutableMap<Int, Pair<View, DecorProvider>> = HashMap()
+
+    fun addDecorProvider(decorProvider: DecorProvider, @Surface.Rotation rotation: Int) {
+        val view = decorProvider.inflateView(layoutInflater, rootView, rotation)
         viewProviderMap[decorProvider.viewId] = Pair(view, decorProvider)
     }
 
@@ -47,35 +56,4 @@
             viewProviderMap.remove(id)
         }
     }
-
-    /**
-     * Apply new configuration info into views.
-     * @param filterIds target view ids. Apply to all if null.
-     * @param rotation current or new rotation direction.
-     * @param displayUniqueId new displayUniqueId if any.
-     */
-    fun onReloadResAndMeasure(
-        filterIds: Array<Int>? = null,
-        reloadToken: Int,
-        @Surface.Rotation rotation: Int,
-        displayUniqueId: String? = null
-    ) {
-        filterIds?.forEach { id ->
-            viewProviderMap[id]?.let {
-                it.second.onReloadResAndMeasure(
-                        view = it.first,
-                        reloadToken = reloadToken,
-                        displayUniqueId = displayUniqueId,
-                        rotation = rotation)
-            }
-        } ?: run {
-            viewProviderMap.values.forEach {
-                it.second.onReloadResAndMeasure(
-                        view = it.first,
-                        reloadToken = reloadToken,
-                        displayUniqueId = displayUniqueId,
-                        rotation = rotation)
-            }
-        }
-    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
index 136f135..7afd7e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.decor
 
-import android.content.Context
 import android.content.res.Resources
 import android.view.DisplayCutout
 import android.view.LayoutInflater
@@ -77,21 +76,12 @@
     private val layoutId: Int
 ) : CornerDecorProvider() {
 
-    override fun onReloadResAndMeasure(
-        view: View,
-        reloadToken: Int,
-        rotation: Int,
-        displayUniqueId: String?
-    ) {
-        // Do nothing here because it is handled inside PrivacyDotViewController
-    }
-
     override fun inflateView(
-        context: Context,
+        inflater: LayoutInflater,
         parent: ViewGroup,
         @Surface.Rotation rotation: Int
     ): View {
-        LayoutInflater.from(context).inflate(layoutId, parent, true)
+        inflater.inflate(layoutId, parent, true)
         return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
deleted file mode 100644
index 4388b8b..0000000
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
+++ /dev/null
@@ -1,86 +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.systemui.decor
-
-import android.view.DisplayCutout
-import com.android.systemui.R
-
-class RoundedCornerDecorProviderFactory(
-    private val roundedCornerResDelegate: RoundedCornerResDelegate
-) : DecorProviderFactory() {
-
-    override val hasProviders: Boolean
-        get() = roundedCornerResDelegate.run {
-            // We don't consider isMultipleRadius here because it makes no sense if size is zero.
-            topRoundedSize.width > 0 || bottomRoundedSize.width > 0
-        }
-
-    override val providers: List<DecorProvider>
-    get() {
-        val hasTop = roundedCornerResDelegate.topRoundedSize.width > 0
-        val hasBottom = roundedCornerResDelegate.bottomRoundedSize.width > 0
-        return when {
-            hasTop && hasBottom -> listOf(
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_top_left,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                    roundedCornerResDelegate = roundedCornerResDelegate),
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_top_right,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                    roundedCornerResDelegate = roundedCornerResDelegate),
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_bottom_left,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                    roundedCornerResDelegate = roundedCornerResDelegate),
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_bottom_right,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                    roundedCornerResDelegate = roundedCornerResDelegate)
-            )
-            hasTop -> listOf(
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_top_left,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                    roundedCornerResDelegate = roundedCornerResDelegate),
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_top_right,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                    roundedCornerResDelegate = roundedCornerResDelegate)
-            )
-            hasBottom -> listOf(
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_bottom_left,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                    roundedCornerResDelegate = roundedCornerResDelegate),
-                RoundedCornerDecorProviderImpl(
-                    viewId = R.id.rounded_corner_bottom_right,
-                    alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
-                    alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                    roundedCornerResDelegate = roundedCornerResDelegate)
-            )
-            else -> emptyList()
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
deleted file mode 100644
index 90ff950..0000000
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+++ /dev/null
@@ -1,192 +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.systemui.decor
-
-import android.content.Context
-import android.view.DisplayCutout
-import android.view.Gravity
-import android.view.Surface
-import android.view.View
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
-import com.android.systemui.R
-
-class RoundedCornerDecorProviderImpl(
-    override val viewId: Int,
-    @DisplayCutout.BoundsPosition override val alignedBound1: Int,
-    @DisplayCutout.BoundsPosition override val alignedBound2: Int,
-    private val roundedCornerResDelegate: RoundedCornerResDelegate
-) : CornerDecorProvider() {
-
-    private val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-
-    override fun inflateView(
-        context: Context,
-        parent: ViewGroup,
-        @Surface.Rotation rotation: Int
-    ): View {
-        return ImageView(context).also { view ->
-            // View
-            view.id = viewId
-            initView(view, rotation)
-
-            // LayoutParams
-            val layoutSize = if (isTop) {
-                roundedCornerResDelegate.topRoundedSize
-            } else {
-                roundedCornerResDelegate.bottomRoundedSize
-            }
-            val params = FrameLayout.LayoutParams(
-                    layoutSize.width,
-                    layoutSize.height,
-                    alignedBound1.toLayoutGravity(rotation) or
-                            alignedBound2.toLayoutGravity(rotation))
-
-            // AddView
-            parent.addView(view, params)
-        }
-    }
-
-    private fun initView(view: ImageView, @Surface.Rotation rotation: Int) {
-        view.setRoundedCornerImage(roundedCornerResDelegate, isTop)
-        view.adjustRotation(alignedBounds, rotation)
-        view.setColorFilter(IMAGE_TINT_COLOR)
-    }
-
-    override fun onReloadResAndMeasure(
-        view: View,
-        reloadToken: Int,
-        @Surface.Rotation rotation: Int,
-        displayUniqueId: String?
-    ) {
-        roundedCornerResDelegate.updateDisplayUniqueId(displayUniqueId, reloadToken)
-
-        initView((view as ImageView), rotation)
-
-        val layoutSize = if (isTop) {
-            roundedCornerResDelegate.topRoundedSize
-        } else {
-            roundedCornerResDelegate.bottomRoundedSize
-        }
-        (view.layoutParams as FrameLayout.LayoutParams).let {
-            it.width = layoutSize.width
-            it.height = layoutSize.height
-            it.gravity = alignedBound1.toLayoutGravity(rotation) or
-                    alignedBound2.toLayoutGravity(rotation)
-            view.setLayoutParams(it)
-        }
-    }
-}
-
-private const val IMAGE_TINT_COLOR: Int = 0xFF000000.toInt()
-
-@DisplayCutout.BoundsPosition
-private fun Int.toLayoutGravity(@Surface.Rotation rotation: Int): Int = when (rotation) {
-    Surface.ROTATION_0 -> when (this) {
-        DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.LEFT
-        DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.TOP
-        DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.RIGHT
-        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.BOTTOM
-    }
-    Surface.ROTATION_90 -> when (this) {
-        DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.BOTTOM
-        DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.LEFT
-        DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.TOP
-        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
-    }
-    Surface.ROTATION_270 -> when (this) {
-        DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.TOP
-        DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.RIGHT
-        DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.BOTTOM
-        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
-    }
-    else /* Surface.ROTATION_180 */ -> when (this) {
-        DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.RIGHT
-        DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.BOTTOM
-        DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.LEFT
-        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.TOP
-    }
-}
-
-private fun ImageView.setRoundedCornerImage(
-    resDelegate: RoundedCornerResDelegate,
-    isTop: Boolean
-) {
-    val drawable = if (isTop)
-        resDelegate.topRoundedDrawable
-    else
-        resDelegate.bottomRoundedDrawable
-
-    if (drawable != null) {
-        setImageDrawable(drawable)
-    } else {
-        setImageResource(
-                if (isTop)
-                    R.drawable.rounded_corner_top
-                else
-                    R.drawable.rounded_corner_bottom
-        )
-    }
-}
-
-/**
- * Configures the rounded corner drawable's view matrix based on the gravity.
- *
- * The gravity describes which corner to configure for, and the drawable we are rotating is assumed
- * to be oriented for the top-left corner of the device regardless of the target corner.
- * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
- * y-axis for the top-right and bottom-left corners.
- */
-private fun ImageView.adjustRotation(alignedBounds: List<Int>, @Surface.Rotation rotation: Int) {
-    var newRotation = 0F
-    var newScaleX = 1F
-    var newScaleY = 1F
-
-    val isTop = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-    val isLeft = alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT)
-    when (rotation) {
-        Surface.ROTATION_0 -> when {
-            isTop && isLeft -> {}
-            isTop && !isLeft -> { newScaleX = -1F }
-            !isTop && isLeft -> { newScaleY = -1F }
-            else /* !isTop && !isLeft */ -> { newRotation = 180F }
-        }
-        Surface.ROTATION_90 -> when {
-            isTop && isLeft -> { newScaleY = -1F }
-            isTop && !isLeft -> {}
-            !isTop && isLeft -> { newRotation = 180F }
-            else /* !isTop && !isLeft */ -> { newScaleX = -1F }
-        }
-        Surface.ROTATION_270 -> when {
-            isTop && isLeft -> { newScaleX = -1F }
-            isTop && !isLeft -> { newRotation = 180F }
-            !isTop && isLeft -> {}
-            else /* !isTop && !isLeft */ -> { newScaleY = -1F }
-        }
-        else /* Surface.ROTATION_180 */ -> when {
-            isTop && isLeft -> { newRotation = 180F }
-            isTop && !isLeft -> { newScaleY = -1F }
-            !isTop && isLeft -> { newScaleX = -1F }
-            else /* !isTop && !isLeft */ -> {}
-        }
-    }
-
-    this.rotation = newRotation
-    this.scaleX = newScaleX
-    this.scaleY = newScaleY
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
index 256c675..c817f89 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
@@ -36,8 +36,6 @@
     private val density: Float
         get() = res.displayMetrics.density
 
-    private var reloadToken: Int = 0
-
     var isMultipleRadius: Boolean = false
         private set
 
@@ -62,26 +60,12 @@
         reloadMeasures()
     }
 
-    private fun reloadAll(newReloadToken: Int) {
-        if (reloadToken == newReloadToken) {
-            return
-        }
-        reloadToken = newReloadToken
+    fun reloadAll(newDisplayUniqueId: String?) {
+        displayUniqueId = newDisplayUniqueId
         reloadDrawables()
         reloadMeasures()
     }
 
-    fun updateDisplayUniqueId(newDisplayUniqueId: String?, newReloadToken: Int?) {
-        if (displayUniqueId != newDisplayUniqueId) {
-            displayUniqueId = newDisplayUniqueId
-            newReloadToken ?.let { reloadToken = it }
-            reloadDrawables()
-            reloadMeasures()
-        } else {
-            newReloadToken?.let { reloadAll(it) }
-        }
-    }
-
     private fun reloadDrawables() {
         val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
         isMultipleRadius = getIsMultipleRadius(configIdx)
@@ -101,6 +85,34 @@
                 arrayResId = R.array.config_roundedCornerBottomDrawableArray,
                 backupDrawableId = R.drawable.rounded_corner_bottom
         ) ?: roundedDrawable
+
+        // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
+        // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
+        if (isMultipleRadius) {
+            roundedSize = Size(
+                    roundedDrawable?.intrinsicWidth ?: 0,
+                    roundedDrawable?.intrinsicHeight ?: 0)
+            topRoundedDrawable?.let {
+                topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
+            }
+            bottomRoundedDrawable?.let {
+                bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
+            }
+        } else {
+            val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
+            val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
+            val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
+            roundedSize = Size(defaultRadius, defaultRadius)
+            topRoundedSize = Size(topRadius, topRadius)
+            bottomRoundedSize = Size(bottomRadius, bottomRadius)
+        }
+
+        if (topRoundedSize.width == 0) {
+            topRoundedSize = roundedSize
+        }
+        if (bottomRoundedSize.width == 0) {
+            bottomRoundedSize = roundedSize
+        }
     }
 
     private fun reloadMeasures(roundedSizeFactor: Int? = null) {
@@ -125,8 +137,8 @@
             bottomRoundedSize = Size(bottomRadius, bottomRadius)
         }
 
-        if (roundedSizeFactor != null && roundedSizeFactor > 0) {
-            val length: Int = (roundedSizeFactor * density).toInt()
+        roundedSizeFactor ?.let {
+            val length: Int = (it * density).toInt()
             roundedSize = Size(length, length)
         }
 
@@ -138,11 +150,7 @@
         }
     }
 
-    fun updateTuningSizeFactor(factor: Int?, newReloadToken: Int) {
-        if (reloadToken == newReloadToken) {
-            return
-        }
-        reloadToken = newReloadToken
+    fun updateTuningSizeFactor(factor: Int) {
         reloadMeasures(factor)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
new file mode 100644
index 0000000..aaa34ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
@@ -0,0 +1,116 @@
+/*
+ * 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.systemui.dreams;
+
+import android.annotation.NonNull;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.policy.CallbackController;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+/***
+ * {@link DreamOverlayNotificationCountProvider} provides the current notification count to
+ * registered callbacks.
+ */
+@SysUISingleton
+public class DreamOverlayNotificationCountProvider
+        implements CallbackController<DreamOverlayNotificationCountProvider.Callback> {
+    private final Set<String> mNotificationKeys = new HashSet<>();
+    private final List<Callback> mCallbacks = new ArrayList<>();
+
+    private final NotificationHandler mNotificationHandler = new NotificationHandler() {
+        @Override
+        public void onNotificationPosted(
+                StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
+            mNotificationKeys.add(sbn.getKey());
+            reportNotificationCountChanged();
+        }
+
+        @Override
+        public void onNotificationRemoved(
+                StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
+            mNotificationKeys.remove(sbn.getKey());
+            reportNotificationCountChanged();
+        }
+
+        @Override
+        public void onNotificationRemoved(
+                StatusBarNotification sbn,
+                NotificationListenerService.RankingMap rankingMap,
+                int reason) {
+            mNotificationKeys.remove(sbn.getKey());
+            reportNotificationCountChanged();
+        }
+
+        @Override
+        public void onNotificationRankingUpdate(NotificationListenerService.RankingMap rankingMap) {
+        }
+
+        @Override
+        public void onNotificationsInitialized() {
+        }
+    };
+
+    @Inject
+    public DreamOverlayNotificationCountProvider(
+            NotificationListener notificationListener) {
+        notificationListener.addNotificationHandler(mNotificationHandler);
+        Arrays.stream(notificationListener.getActiveNotifications())
+                .forEach(sbn -> mNotificationKeys.add(sbn.getKey()));
+    }
+
+    @Override
+    public void addCallback(@NonNull Callback callback) {
+        if (!mCallbacks.contains(callback)) {
+            mCallbacks.add(callback);
+            callback.onNotificationCountChanged(mNotificationKeys.size());
+        }
+    }
+
+    @Override
+    public void removeCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    private void reportNotificationCountChanged() {
+        final int notificationCount = mNotificationKeys.size();
+        mCallbacks.forEach(callback -> callback.onNotificationCountChanged(notificationCount));
+    }
+
+    /**
+     * A callback to be registered with {@link DreamOverlayNotificationCountProvider} to receive
+     * changes to the current notification count.
+     */
+    public interface Callback {
+        /**
+         * Called when the notification count has changed.
+         * @param count The current notification count.
+         */
+        void onNotificationCountChanged(int count);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index 761f28c..d4909c78 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -27,16 +27,12 @@
 import android.net.NetworkRequest;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.StatusBarNotification;
 import android.text.format.DateFormat;
 import android.util.PluralsMessageFormatter;
 
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -62,7 +58,7 @@
     private final Resources mResources;
     private final DateFormatUtil mDateFormatUtil;
     private final IndividualSensorPrivacyController mSensorPrivacyController;
-    private final NotificationListener mNotificationListener;
+    private final DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider;
     private final ZenModeController mZenModeController;
     private final Executor mMainExecutor;
 
@@ -96,35 +92,6 @@
     private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
             nextAlarm -> updateAlarmStatusIcon();
 
-    private final NotificationHandler mNotificationHandler = new NotificationHandler() {
-        @Override
-        public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
-            updateNotificationsStatusIcon();
-        }
-
-        @Override
-        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
-            updateNotificationsStatusIcon();
-        }
-
-        @Override
-        public void onNotificationRemoved(
-                StatusBarNotification sbn,
-                RankingMap rankingMap,
-                int reason) {
-            updateNotificationsStatusIcon();
-        }
-
-        @Override
-        public void onNotificationRankingUpdate(RankingMap rankingMap) {
-        }
-
-        @Override
-        public void onNotificationsInitialized() {
-            updateNotificationsStatusIcon();
-        }
-    };
-
     private final ZenModeController.Callback mZenModeCallback = new ZenModeController.Callback() {
         @Override
         public void onZenChanged(int zen) {
@@ -132,6 +99,14 @@
         }
     };
 
+    private final DreamOverlayNotificationCountProvider.Callback mNotificationCountCallback =
+            notificationCount -> showIcon(
+                    DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS,
+                    notificationCount > 0,
+                    notificationCount > 0
+                            ? buildNotificationsContentDescription(notificationCount)
+                            : null);
+
     @Inject
     public DreamOverlayStatusBarViewController(
             DreamOverlayStatusBarView view,
@@ -143,7 +118,7 @@
             NextAlarmController nextAlarmController,
             DateFormatUtil dateFormatUtil,
             IndividualSensorPrivacyController sensorPrivacyController,
-            NotificationListener notificationListener,
+            DreamOverlayNotificationCountProvider dreamOverlayNotificationCountProvider,
             ZenModeController zenModeController) {
         super(view);
         mResources = resources;
@@ -154,20 +129,14 @@
         mNextAlarmController = nextAlarmController;
         mDateFormatUtil = dateFormatUtil;
         mSensorPrivacyController = sensorPrivacyController;
-        mNotificationListener = notificationListener;
+        mDreamOverlayNotificationCountProvider = dreamOverlayNotificationCountProvider;
         mZenModeController = zenModeController;
-
-        // Handlers can be added to NotificationListener, but apparently they can't be removed. So
-        // add the handler here in the constructor rather than in onViewAttached to avoid confusion.
-        mNotificationListener.addNotificationHandler(mNotificationHandler);
     }
 
     @Override
     protected void onViewAttached() {
         mIsAttached = true;
 
-        updateNotificationsStatusIcon();
-
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
         updateWifiUnavailableStatusIcon();
 
@@ -180,6 +149,7 @@
         mZenModeController.addCallback(mZenModeCallback);
         updatePriorityModeStatusIcon();
 
+        mDreamOverlayNotificationCountProvider.addCallback(mNotificationCountCallback);
         mTouchInsetSession.addViewToTracking(mView);
     }
 
@@ -189,6 +159,7 @@
         mSensorPrivacyController.removeCallback(mSensorCallback);
         mNextAlarmController.removeCallback(mNextAlarmCallback);
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+        mDreamOverlayNotificationCountProvider.removeCallback(mNotificationCountCallback);
         mTouchInsetSession.clear();
 
         mIsAttached = false;
@@ -231,24 +202,6 @@
                 micBlocked && cameraBlocked);
     }
 
-    private void updateNotificationsStatusIcon() {
-        if (mView == null) {
-            // It is possible for this method to be called before the view is attached, which makes
-            // null-checking necessary.
-            return;
-        }
-
-        final StatusBarNotification[] notifications =
-                mNotificationListener.getActiveNotifications();
-        final int notificationCount = notifications != null ? notifications.length : 0;
-        showIcon(
-                DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS,
-                notificationCount > 0,
-                notificationCount > 0
-                        ? buildNotificationsContentDescription(notificationCount)
-                        : null);
-    }
-
     private String buildNotificationsContentDescription(int notificationCount) {
         return PluralsMessageFormatter.format(
                 mResources,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
index 0b98767..4f0455d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java
@@ -44,10 +44,13 @@
 public class DraggableConstraintLayout extends ConstraintLayout
         implements ViewTreeObserver.OnComputeInternalInsetsListener {
 
+    private static final float VELOCITY_DP_PER_MS = 1;
+
     private final SwipeDismissHandler mSwipeDismissHandler;
     private final GestureDetector mSwipeDetector;
     private View mActionsContainer;
     private SwipeDismissCallbacks mCallbacks;
+    private final DisplayMetrics mDisplayMetrics;
 
     /**
      * Stores the callbacks when the view is interacted with or dismissed.
@@ -86,6 +89,9 @@
     public DraggableConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
+        mDisplayMetrics = new DisplayMetrics();
+        mContext.getDisplay().getRealMetrics(mDisplayMetrics);
+
         mSwipeDismissHandler = new SwipeDismissHandler(mContext, this);
         setOnTouchListener(mSwipeDismissHandler);
 
@@ -283,7 +289,8 @@
         }
 
         void dismiss() {
-            ValueAnimator anim = createSwipeDismissAnimation(3);
+            float velocityPxPerMs = FloatingWindowUtil.dpToPx(mDisplayMetrics, VELOCITY_DP_PER_MS);
+            ValueAnimator anim = createSwipeDismissAnimation(velocityPxPerMs);
             mCallbacks.onSwipeDismissInitiated(anim);
             dismiss(anim);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 8f78feb..3620e84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -494,6 +494,9 @@
         }
         notificationPanelController
             .setKeyguardTransitionProgress(keyguardAlpha, keyguardTranslationY)
+
+        val statusBarAlpha = if (useSplitShade) keyguardAlpha else -1f
+        notificationPanelController.setKeyguardStatusBarAlpha(statusBarAlpha)
     }
 
     private fun setDragDownAmountAnimated(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
index ff0e47f..e436ccf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
@@ -77,6 +77,8 @@
     private val secureSettings: SecureSettings,
     private val globalSettings: GlobalSettings
 ) : CoreStartable(context), KeyguardNotificationVisibilityProvider {
+    private val showSilentNotifsUri =
+            secureSettings.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS)
     private val onStateChangedListeners = ListenerSet<Consumer<String>>()
     private var hideSilentNotificationsOnLockscreen: Boolean = false
 
@@ -100,6 +102,9 @@
         // register lockscreen settings changed callbacks:
         val settingsObserver: ContentObserver = object : ContentObserver(handler) {
             override fun onChange(selfChange: Boolean, uri: Uri?) {
+                if (uri == showSilentNotifsUri) {
+                    readShowSilentNotificationSetting()
+                }
                 if (keyguardStateController.isShowing) {
                     notifyStateChanged("Settings $uri changed")
                 }
@@ -152,62 +157,50 @@
         onStateChangedListeners.forEach { it.accept(reason) }
     }
 
-    override fun shouldHideNotification(entry: NotificationEntry): Boolean {
-        val sbn = entry.sbn
-        // FILTER OUT the notification when the keyguard is showing and...
-        if (keyguardStateController.isShowing) {
-            // ... user settings or the device policy manager doesn't allow lockscreen
-            // notifications;
-            if (!lockscreenUserManager.shouldShowLockscreenNotifications()) {
-                return true
-            }
-            val currUserId: Int = lockscreenUserManager.currentUserId
-            val notifUserId =
-                    if (sbn.user.identifier == UserHandle.USER_ALL) currUserId
-                    else sbn.user.identifier
-
-            // ... user is in lockdown
-            if (keyguardUpdateMonitor.isUserInLockdown(currUserId) ||
-                    keyguardUpdateMonitor.isUserInLockdown(notifUserId)) {
-                return true
-            }
-
-            // ... device is in public mode and the user's settings doesn't allow
-            // notifications to show in public mode
-            if (lockscreenUserManager.isLockscreenPublicMode(currUserId) ||
-                    lockscreenUserManager.isLockscreenPublicMode(notifUserId)) {
-                if (entry.ranking.lockscreenVisibilityOverride == Notification.VISIBILITY_SECRET) {
-                    return true
-                }
-                if (!lockscreenUserManager.userAllowsNotificationsInPublic(currUserId) ||
-                        !lockscreenUserManager.userAllowsNotificationsInPublic(
-                                notifUserId)) {
-                    return true
-                }
-            }
-
-            // ... neither this notification nor its group have high enough priority
-            // to be shown on the lockscreen
-            if (entry.parent != null) {
-                val parent = entry.parent
-                if (priorityExceedsLockscreenShowingThreshold(parent)) {
-                    return false
-                }
-            }
-            return !priorityExceedsLockscreenShowingThreshold(entry)
-        }
-        return false
+    override fun shouldHideNotification(entry: NotificationEntry): Boolean = when {
+        // Keyguard state doesn't matter if the keyguard is not showing.
+        !keyguardStateController.isShowing -> false
+        // Notifications not allowed on the lockscreen, always hide.
+        !lockscreenUserManager.shouldShowLockscreenNotifications() -> true
+        // User settings do not allow this notification on the lockscreen, so hide it.
+        userSettingsDisallowNotification(entry) -> true
+        // Parent priority is high enough to be shown on the lockscreen, do not hide.
+        entry.parent?.let(::priorityExceedsLockscreenShowingThreshold) == true -> false
+        // Entry priority is high enough to be shown on the lockscreen, do not hide.
+        priorityExceedsLockscreenShowingThreshold(entry) -> false
+        // Priority is too low, hide.
+        else -> true
     }
 
-    private fun priorityExceedsLockscreenShowingThreshold(entry: ListEntry?): Boolean =
-        when {
-            entry == null -> false
-            hideSilentNotificationsOnLockscreen -> highPriorityProvider.isHighPriority(entry)
-            else -> entry.representativeEntry?.ranking?.isAmbient == false
+    private fun userSettingsDisallowNotification(entry: NotificationEntry): Boolean {
+        fun disallowForUser(user: Int) = when {
+            // user is in lockdown, always disallow
+            keyguardUpdateMonitor.isUserInLockdown(user) -> true
+            // device isn't public, no need to check public-related settings, so allow
+            !lockscreenUserManager.isLockscreenPublicMode(user) -> false
+            // entry is meant to be secret on the lockscreen, disallow
+            entry.ranking.lockscreenVisibilityOverride == Notification.VISIBILITY_SECRET -> true
+            // disallow if user disallows notifications in public
+            else -> !lockscreenUserManager.userAllowsNotificationsInPublic(user)
         }
+        val currentUser = lockscreenUserManager.currentUserId
+        val notifUser = entry.sbn.user.identifier
+        return when {
+            disallowForUser(currentUser) -> true
+            notifUser == UserHandle.USER_ALL -> false
+            notifUser == currentUser -> false
+            else -> disallowForUser(notifUser)
+        }
+    }
+
+    private fun priorityExceedsLockscreenShowingThreshold(entry: ListEntry): Boolean = when {
+        hideSilentNotificationsOnLockscreen -> highPriorityProvider.isHighPriority(entry)
+        else -> entry.representativeEntry?.ranking?.isAmbient == false
+    }
 
     private fun readShowSilentNotificationSetting() {
-        hideSilentNotificationsOnLockscreen =
+        val showSilentNotifs =
                 secureSettings.getBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, true)
+        hideSilentNotificationsOnLockscreen = !showSilentNotifs
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 1932680..a2d22bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -3745,6 +3745,14 @@
         mTransitionToFullShadeProgress = transitionToFullShadeProgress;
     }
 
+    /**
+     * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer
+     * is fully hidden, while 0 means the bouncer is visible.
+     */
+    public void setBouncerHiddenFraction(float expansion) {
+        mScrimController.setBouncerHiddenFraction(expansion);
+    }
+
     @VisibleForTesting
     public void updateScrimController() {
         Trace.beginSection("CentralSurfaces#updateScrimController");
@@ -3797,6 +3805,8 @@
             mScrimController.transitionTo(ScrimState.AOD);
         } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) {
             mScrimController.transitionTo(ScrimState.KEYGUARD);
+        } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) {
+            mScrimController.transitionTo(ScrimState.DREAMING);
         } else {
             mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
         }
@@ -4203,6 +4213,7 @@
             new KeyguardUpdateMonitorCallback() {
                 @Override
                 public void onDreamingStateChanged(boolean dreaming) {
+                    updateScrimController();
                     if (dreaming) {
                         maybeEscalateHeadsUp();
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index a70ba82..57d6348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -229,6 +229,11 @@
     private boolean mShowingKeyguardHeadsUp;
     private StatusBarSystemEventAnimator mSystemEventAnimator;
 
+    /**
+     * The alpha value to be set on the View. If -1, this value is to be ignored.
+     */
+    private float mExplicitAlpha = -1f;
+
     @Inject
     public KeyguardStatusBarViewController(
             KeyguardStatusBarView view,
@@ -425,9 +430,15 @@
 
         float alphaQsExpansion = 1 - Math.min(
                 1, mNotificationPanelViewStateProvider.getLockscreenShadeDragProgress() * 2);
-        float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
-                * mKeyguardStatusBarAnimateAlpha
-                * (1.0f - mKeyguardHeadsUpShowingAmount);
+
+        float newAlpha;
+        if (mExplicitAlpha != -1) {
+            newAlpha = mExplicitAlpha;
+        } else {
+            newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
+                    * mKeyguardStatusBarAnimateAlpha
+                    * (1.0f - mKeyguardHeadsUpShowingAmount);
+        }
 
         boolean hideForBypass =
                 mFirstBypassAttempt && mKeyguardUpdateMonitor.shouldListenForFace()
@@ -510,7 +521,17 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardStatusBarView:");
         pw.println("  mBatteryListening: " + mBatteryListening);
+        pw.println("  mExplicitAlpha: " + mExplicitAlpha);
         mView.dump(fd, pw, args);
     }
 
+    /**
+     * Sets the alpha to be set on the view.
+     *
+     * @param alpha a value between 0 and 1. -1 if the value is to be reset/ignored.
+     */
+    public void setAlpha(float alpha) {
+        mExplicitAlpha = alpha;
+        updateViewState();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 999ebc1..2d16b52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -2682,6 +2682,15 @@
         updateClock();
     }
 
+    /**
+     * Sets the alpha value to be set on the keyguard status bar.
+     *
+     * @param alpha value between 0 and 1. -1 if the value is to be reset.
+     */
+    public void setKeyguardStatusBarAlpha(float alpha) {
+        mKeyguardStatusBarViewController.setAlpha(alpha);
+    }
+
     private void trackMovement(MotionEvent event) {
         if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7e22510..e684c2005 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -138,6 +138,13 @@
     private boolean mUnOcclusionAnimationRunning;
 
     /**
+     * The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If
+     * 0, the bouncer is visible.
+     */
+    @FloatRange(from = 0, to = 1)
+    private float mBouncerHiddenFraction = KeyguardBouncer.EXPANSION_HIDDEN;
+
+    /**
      * Set whether an unocclusion animation is currently running on the notification panel. Used
      * to avoid bright flickers of the notification scrim.
      */
@@ -586,6 +593,7 @@
 
             boolean relevantState = (mState == ScrimState.UNLOCKED
                     || mState == ScrimState.KEYGUARD
+                    || mState == ScrimState.DREAMING
                     || mState == ScrimState.SHADE_LOCKED
                     || mState == ScrimState.PULSING);
             if (!(relevantState && mExpansionAffectsAlpha) || mAnimatingPanelExpansionOnUnlock) {
@@ -677,6 +685,21 @@
     }
 
     /**
+     * Updates the percentage of the bouncer which is hidden.
+     */
+    public void setBouncerHiddenFraction(@FloatRange(from = 0, to = 1) float bouncerHiddenAmount) {
+        if (mBouncerHiddenFraction == bouncerHiddenAmount) {
+            return;
+        }
+        mBouncerHiddenFraction = bouncerHiddenAmount;
+        if (mState == ScrimState.DREAMING) {
+            // Only the dreaming state requires this for the scrim calculation, so we should
+            // only trigger an update if dreaming.
+            applyAndDispatchState();
+        }
+    }
+
+    /**
      * If QS and notification scrims should not overlap, and should be clipped to each other's
      * bounds instead.
      */
@@ -741,7 +764,7 @@
             return;
         }
 
-        if (mState == ScrimState.UNLOCKED) {
+        if (mState == ScrimState.UNLOCKED || mState == ScrimState.DREAMING) {
             // Darken scrim as you pull down the shade when unlocked, unless the shade is expanding
             // because we're doing the screen off animation OR the shade is collapsing because
             // we're playing the unlock animation
@@ -759,14 +782,30 @@
                     mNotificationsAlpha = MathUtils.constrainedMap(0f, 1f, 0.3f, 0.75f,
                             mPanelExpansionFraction);
                 }
+                mBehindTint = mState.getBehindTint();
                 mInFrontAlpha = 0;
             }
+
+            if (mBouncerHiddenFraction != KeyguardBouncer.EXPANSION_HIDDEN) {
+                final float interpolatedFraction =
+                        BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(
+                                mBouncerHiddenFraction);
+                mBehindAlpha = MathUtils.lerp(mDefaultScrimAlpha, mBehindAlpha,
+                        interpolatedFraction);
+                mBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+                        mBehindTint,
+                        interpolatedFraction);
+            }
         } else if (mState == ScrimState.AUTH_SCRIMMED_SHADE) {
             float behindFraction = getInterpolatedFraction();
             behindFraction = (float) Math.pow(behindFraction, 0.8f);
 
             mBehindAlpha = behindFraction * mDefaultScrimAlpha;
             mNotificationsAlpha = mBehindAlpha;
+            if (mClipsQsScrim) {
+                mBehindAlpha = 1;
+                mBehindTint = Color.BLACK;
+            }
         } else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
                 || mState == ScrimState.PULSING) {
             Pair<Integer, Float> result = calculateBackStateForState(mState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 9028870..47b7058 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -262,6 +262,25 @@
                 updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
             }
         }
+    },
+
+    DREAMING {
+        @Override
+        public void prepare(ScrimState previousState) {
+            mFrontTint = Color.TRANSPARENT;
+            mBehindTint = Color.BLACK;
+            mNotifTint = mClipQsScrim ? Color.BLACK : Color.TRANSPARENT;
+
+            mFrontAlpha = 0;
+            mBehindAlpha = mClipQsScrim ? 1 : 0;
+            mNotifAlpha = 0;
+
+            mBlankScreen = false;
+
+            if (mClipQsScrim) {
+                updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK);
+            }
+        }
     };
 
     boolean mBlankScreen = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index b847885..ff352e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -121,9 +121,13 @@
     private final FoldAodAnimationController mFoldAodAnimationController;
     private KeyguardMessageAreaController mKeyguardMessageAreaController;
     private final Lazy<ShadeController> mShadeController;
+
     private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
+        private boolean mBouncerAnimating;
+
         @Override
         public void onFullyShown() {
+            mBouncerAnimating = false;
             updateStates();
             mCentralSurfaces.wakeUpIfDozing(SystemClock.uptimeMillis(),
                     mCentralSurfaces.getBouncerContainer(), "BOUNCER_VISIBLE");
@@ -131,16 +135,19 @@
 
         @Override
         public void onStartingToHide() {
+            mBouncerAnimating = true;
             updateStates();
         }
 
         @Override
         public void onStartingToShow() {
+            mBouncerAnimating = true;
             updateStates();
         }
 
         @Override
         public void onFullyHidden() {
+            mBouncerAnimating = false;
         }
 
         @Override
@@ -148,6 +155,9 @@
             if (mAlternateAuthInterceptor != null) {
                 mAlternateAuthInterceptor.setBouncerExpansionChanged(expansion);
             }
+            if (mBouncerAnimating) {
+                mCentralSurfaces.setBouncerHiddenFraction(expansion);
+            }
             updateStates();
         }
 
@@ -155,6 +165,7 @@
         public void onVisibilityChanged(boolean isVisible) {
             if (!isVisible) {
                 cancelPostAuthActions();
+                mCentralSurfaces.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN);
             }
             if (mAlternateAuthInterceptor != null) {
                 mAlternateAuthInterceptor.onBouncerVisibilityChanged();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index ac78626..ec92adb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -60,11 +61,9 @@
 import android.view.Display;
 import android.view.DisplayCutout;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
@@ -103,7 +102,7 @@
     private SecureSettings mSecureSettings;
     private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
     private FakeThreadFactory mThreadFactory;
-    private ArrayList<DecorProvider> mPrivacyDecorProviders;
+    private ArrayList<DecorProvider> mDecorProviders;
     @Mock
     private Display mDisplay;
     @Mock
@@ -198,43 +197,17 @@
         reset(mTunerService);
     }
 
-    @NonNull
-    private int[] getRoundCornerIdsFromOverlayId(@DisplayCutout.BoundsPosition int overlayId) {
-        switch (overlayId) {
-            case BOUNDS_POSITION_LEFT:
-                return new int[] {
-                        R.id.rounded_corner_top_left,
-                        R.id.rounded_corner_top_left };
-            case BOUNDS_POSITION_TOP:
-                return new int[] {
-                        R.id.rounded_corner_top_left,
-                        R.id.rounded_corner_top_right };
-            case BOUNDS_POSITION_RIGHT:
-                return new int[] {
-                        R.id.rounded_corner_top_right,
-                        R.id.rounded_corner_bottom_right };
-            case BOUNDS_POSITION_BOTTOM:
-                return new int[] {
-                        R.id.rounded_corner_bottom_left,
-                        R.id.rounded_corner_bottom_right };
-            default:
-                throw new IllegalArgumentException("unknown overlayId: " + overlayId);
-        }
-    }
 
-    private void verifyRoundedCornerViewsExist(
+    private void verifyRoundedCornerViewsVisibility(
             @DisplayCutout.BoundsPosition final int overlayId,
-            @View.Visibility final boolean isExist) {
+            @View.Visibility final int visibility) {
         final View overlay = mScreenDecorations.mOverlays[overlayId].getRootView();
-        for (int id: getRoundCornerIdsFromOverlayId(overlayId)) {
-            final View view = overlay.findViewById(id);
-            if (isExist) {
-                assertNotNull(view);
-                assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
-            } else {
-                assertNull(view);
-            }
-        }
+        final View left = overlay.findViewById(R.id.left);
+        final View right = overlay.findViewById(R.id.right);
+        assertNotNull(left);
+        assertNotNull(right);
+        assertThat(left.getVisibility()).isEqualTo(visibility);
+        assertThat(right.getVisibility()).isEqualTo(visibility);
     }
 
     @Nullable
@@ -378,8 +351,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall not exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
 
         // Privacy dots shall exist but invisible
         verifyDotViewsVisibility(View.INVISIBLE);
@@ -407,8 +380,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Privacy dots shall not exist
         verifyDotViewsNullable(true);
@@ -435,8 +408,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Privacy dots shall exist but invisible
         verifyDotViewsVisibility(View.INVISIBLE);
@@ -476,26 +449,21 @@
 
         mScreenDecorations.start();
         View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
-                .findViewById(R.id.rounded_corner_top_left);
+                .findViewById(R.id.left);
         View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
-                .findViewById(R.id.rounded_corner_top_right);
-        ViewGroup.LayoutParams leftParams = leftRoundedCorner.getLayoutParams();
-        ViewGroup.LayoutParams rightParams = rightRoundedCorner.getLayoutParams();
-        assertEquals(leftParams.width, testTopRadius);
-        assertEquals(leftParams.height, testTopRadius);
-        assertEquals(rightParams.width, testTopRadius);
-        assertEquals(rightParams.height, testTopRadius);
-
+                .findViewById(R.id.right);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, new Size(testTopRadius, testTopRadius));
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(rightRoundedCorner, new Size(testTopRadius, testTopRadius));
         leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
-                .findViewById(R.id.rounded_corner_bottom_left);
+                .findViewById(R.id.left);
         rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_BOTTOM].getRootView()
-                .findViewById(R.id.rounded_corner_bottom_right);
-        leftParams = leftRoundedCorner.getLayoutParams();
-        rightParams = rightRoundedCorner.getLayoutParams();
-        assertEquals(leftParams.width, testBottomRadius);
-        assertEquals(leftParams.height, testBottomRadius);
-        assertEquals(rightParams.width, testBottomRadius);
-        assertEquals(rightParams.height, testBottomRadius);
+                .findViewById(R.id.right);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, new Size(testBottomRadius, testBottomRadius));
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(rightRoundedCorner, new Size(testBottomRadius, testBottomRadius));
     }
 
     @Test
@@ -511,27 +479,31 @@
                 .when(mScreenDecorations).getCutout();
 
         mScreenDecorations.start();
-        View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
-                .findViewById(R.id.rounded_corner_top_left);
-        View bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
-                .findViewById(R.id.rounded_corner_bottom_left);
-        ViewGroup.LayoutParams topParams = topRoundedCorner.getLayoutParams();
-        ViewGroup.LayoutParams bottomParams = bottomRoundedCorner.getLayoutParams();
-        assertEquals(topParams.width, testTopRadius);
-        assertEquals(topParams.height, testTopRadius);
-        assertEquals(bottomParams.width, testBottomRadius);
-        assertEquals(bottomParams.height, testBottomRadius);
+        final Size topRadius = new Size(testTopRadius, testTopRadius);
+        final Size bottomRadius = new Size(testBottomRadius, testBottomRadius);
+        View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
+                .findViewById(R.id.left);
+        boolean isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.left);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
 
-        topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
-                .findViewById(R.id.rounded_corner_top_right);
-        bottomRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
-                .findViewById(R.id.rounded_corner_bottom_right);
-        topParams = topRoundedCorner.getLayoutParams();
-        bottomParams = bottomRoundedCorner.getLayoutParams();
-        assertEquals(topParams.width, testTopRadius);
-        assertEquals(topParams.height, testTopRadius);
-        assertEquals(bottomParams.width, testBottomRadius);
-        assertEquals(bottomParams.height, testBottomRadius);
+        View rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
+                .findViewById(R.id.right);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_LEFT, R.id.right);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
+
+        leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
+                .findViewById(R.id.left);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.left);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(leftRoundedCorner, isTop ? topRadius : bottomRadius);
+
+        rightRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_RIGHT].getRootView()
+                .findViewById(R.id.right);
+        isTop = mScreenDecorations.isTopRoundedCorner(BOUNDS_POSITION_RIGHT, R.id.right);
+        verify(mScreenDecorations, atLeastOnce())
+                .setSize(rightRoundedCorner, isTop ? topRadius : bottomRadius);
     }
 
     @Test
@@ -551,8 +523,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Privacy dots shall not exist
         verifyDotViewsNullable(true);
@@ -585,8 +557,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Privacy dots shall exist but invisible
         verifyDotViewsVisibility(View.INVISIBLE);
@@ -645,10 +617,10 @@
 
         // Top rounded corner views shall exist because of cutout
         // but be gone because of no rounded corner
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
         // Bottom rounded corner views shall exist because of privacy dot
         // but be gone because of no rounded corner
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
 
         // Privacy dots shall exist but invisible
         verifyDotViewsVisibility(View.INVISIBLE);
@@ -676,7 +648,7 @@
 
         // Left rounded corner views shall exist because of cutout
         // but be gone because of no rounded corner
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_LEFT, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_LEFT, View.GONE);
 
         // Top privacy dots shall not exist because of no privacy
         verifyDotViewsNullable(true);
@@ -728,8 +700,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Top privacy dots shall not exist because of no privacy dot
         verifyDotViewsNullable(true);
@@ -756,8 +728,8 @@
         verifyOverlaysExistAndAdded(false, true, false, true);
 
         // Rounded corner views shall exist
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, true);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.VISIBLE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.VISIBLE);
 
         // Top privacy dots shall exist but invisible
         verifyDotViewsVisibility(View.INVISIBLE);
@@ -887,7 +859,7 @@
         verifyOverlaysExistAndAdded(true, false, true, false);
 
         // Verify each privacy dot id appears only once
-        mPrivacyDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
+        mDecorProviders.stream().map(DecorProvider::getViewId).forEach(viewId -> {
             int findCount = 0;
             for (OverlayWindow overlay: mScreenDecorations.mOverlays) {
                 if (overlay == null) {
@@ -941,8 +913,8 @@
         // Both top and bottom windows should be added because of privacy dot,
         // but their visibility shall be gone because of no rounding.
         verifyOverlaysExistAndAdded(false, true, false, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
 
         when(mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
@@ -953,8 +925,8 @@
         // Both top and bottom windows should be added because of privacy dot,
         // but their visibility shall be gone because of no rounding.
         verifyOverlaysExistAndAdded(false, true, false, true);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_TOP, false);
-        verifyRoundedCornerViewsExist(BOUNDS_POSITION_BOTTOM, false);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_TOP, View.GONE);
+        verifyRoundedCornerViewsVisibility(BOUNDS_POSITION_BOTTOM, View.GONE);
     }
 
     @Test
@@ -1202,14 +1174,14 @@
         mContext.getOrCreateTestableResources().addOverride(
                 com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
 
-        mPrivacyDecorProviders = new ArrayList<>();
+        mDecorProviders = new ArrayList<>();
         if (privacyDot) {
-            mPrivacyDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
-            mPrivacyDecorProviders.add(mPrivacyDotTopRightDecorProvider);
-            mPrivacyDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
-            mPrivacyDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
+            mDecorProviders.add(mPrivacyDotTopLeftDecorProvider);
+            mDecorProviders.add(mPrivacyDotTopRightDecorProvider);
+            mDecorProviders.add(mPrivacyDotBottomLeftDecorProvider);
+            mDecorProviders.add(mPrivacyDotBottomRightDecorProvider);
         }
-        when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mPrivacyDecorProviders);
+        when(mPrivacyDotDecorProviderFactory.getProviders()).thenReturn(mDecorProviders);
         when(mPrivacyDotDecorProviderFactory.getHasProviders()).thenReturn(privacyDot);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
index 9418b50..f99b20d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
@@ -42,6 +42,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
@@ -50,7 +51,6 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-@Ignore
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 @SmallTest
@@ -66,6 +66,11 @@
 
     private AuthBiometricView mBiometricView;
 
+    @After
+    public void tearDown() {
+        destroyDialog();
+    }
+
     @Test
     public void testOnAuthenticationSucceeded_noConfirmationRequired_sendsActionAuthenticated() {
         initDialog(false /* allowDeviceCredential */, mCallback);
@@ -245,6 +250,7 @@
         // TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle
 
         // Create new dialog and restore the previous state into it
+        destroyDialog();
         initDialog(false /* allowDeviceCredential */, mCallback, state, 10000);
         mBiometricView.mAnimationDurationHideDialog = 10000;
         mBiometricView.setRequireConfirmation(requireConfirmation);
@@ -304,6 +310,12 @@
         waitForIdleSync();
     }
 
+    private void destroyDialog() {
+        if (mBiometricView != null && mBiometricView.isAttachedToWindow()) {
+            ViewUtils.detachView(mBiometricView);
+        }
+    }
+
     @Override
     protected void waitForIdleSync() {
         TestableLooper.get(this).processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
index 5182210..ca74df0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
@@ -19,19 +19,25 @@
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper.RunWithLooper
 import android.view.DisplayCutout
+import android.view.LayoutInflater
 import android.view.Surface
 import android.view.View
+import android.view.ViewGroup
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.eq
 import org.junit.Assert
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mockito.never
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.spy
-import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
 
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper(setAsMainLooper = true)
@@ -39,88 +45,62 @@
 class OverlayWindowTest : SysuiTestCase() {
 
     companion object {
-        private val TEST_DECOR_VIEW_ID_1 = R.id.privacy_dot_top_left_container
-        private val TEST_DECOR_VIEW_ID_2 = R.id.privacy_dot_bottom_right_container
+        private val TEST_DECOR_VIEW_ID = R.id.privacy_dot_bottom_right_container
+        private val TEST_DECOR_LAYOUT_ID = R.layout.privacy_dot_bottom_right
     }
 
     private lateinit var overlay: OverlayWindow
-    private lateinit var decorProvider1: DecorProvider
-    private lateinit var decorProvider2: DecorProvider
+
+    @Mock private lateinit var layoutInflater: LayoutInflater
+    @Mock private lateinit var decorProvider: DecorProvider
 
     @Before
     fun setUp() {
-        decorProvider1 = spy(PrivacyDotCornerDecorProviderImpl(
-                viewId = TEST_DECOR_VIEW_ID_1,
-                alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
-                alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
-                layoutId = R.layout.privacy_dot_top_left))
-        decorProvider2 = spy(PrivacyDotCornerDecorProviderImpl(
-                viewId = TEST_DECOR_VIEW_ID_2,
-                alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
-                alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
-                layoutId = R.layout.privacy_dot_bottom_right))
+        MockitoAnnotations.initMocks(this)
 
-        overlay = OverlayWindow(mContext)
+        layoutInflater = spy(LayoutInflater.from(mContext))
+
+        overlay = OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
+
+        whenever(decorProvider.viewId).thenReturn(TEST_DECOR_VIEW_ID)
+        whenever(decorProvider.inflateView(
+            eq(layoutInflater),
+            eq(overlay.rootView),
+            anyInt())
+        ).then {
+            val layoutInflater = it.getArgument<LayoutInflater>(0)
+            val parent = it.getArgument<ViewGroup>(1)
+            layoutInflater.inflate(TEST_DECOR_LAYOUT_ID, parent)
+            return@then parent.getChildAt(parent.childCount - 1)
+        }
+    }
+
+    @Test
+    fun testAnyBoundsPositionShallNoExceptionForConstructor() {
+        OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_LEFT)
+        OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_TOP)
+        OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_RIGHT)
+        OverlayWindow(layoutInflater, DisplayCutout.BOUNDS_POSITION_BOTTOM)
     }
 
     @Test
     fun testAddProvider() {
         @Surface.Rotation val rotation = Surface.ROTATION_270
-        overlay.addDecorProvider(decorProvider1, rotation)
-        overlay.addDecorProvider(decorProvider2, rotation)
-
-        verify(decorProvider1, times(1)).inflateView(
-                mContext, overlay.rootView, rotation)
-        verify(decorProvider2, times(1)).inflateView(
-                mContext, overlay.rootView, rotation)
-
-        val view1FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
-        Assert.assertNotNull(view1FoundFromRootView)
-        Assert.assertEquals(view1FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_1))
-        val view2FoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_2)
-        Assert.assertNotNull(view2FoundFromRootView)
-        Assert.assertEquals(view2FoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID_2))
+        overlay.addDecorProvider(decorProvider, rotation)
+        verify(decorProvider, Mockito.times(1)).inflateView(
+                eq(layoutInflater), eq(overlay.rootView), eq(rotation))
+        val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
+        Assert.assertNotNull(viewFoundFromRootView)
+        Assert.assertEquals(viewFoundFromRootView, overlay.getView(TEST_DECOR_VIEW_ID))
     }
 
     @Test
     fun testRemoveView() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_270)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_270)
-        overlay.removeView(TEST_DECOR_VIEW_ID_1)
-
-        val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID_1)
+        @Surface.Rotation val rotation = Surface.ROTATION_270
+        overlay.addDecorProvider(decorProvider, rotation)
+        overlay.removeView(TEST_DECOR_VIEW_ID)
+        val viewFoundFromRootView = overlay.rootView.findViewById<View>(TEST_DECOR_VIEW_ID)
         Assert.assertNull(viewFoundFromRootView)
-        Assert.assertNull(overlay.getView(TEST_DECOR_VIEW_ID_1))
-    }
-
-    @Test
-    fun testOnReloadResAndMeasureWithoutIds() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
-
-        overlay.onReloadResAndMeasure(
-                reloadToken = 1,
-                rotation = Surface.ROTATION_90,
-                displayUniqueId = null)
-        verify(decorProvider1, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
-        verify(decorProvider2, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
-    }
-
-    @Test
-    fun testOnReloadResAndMeasureWithIds() {
-        overlay.addDecorProvider(decorProvider1, Surface.ROTATION_0)
-        overlay.addDecorProvider(decorProvider2, Surface.ROTATION_0)
-
-        overlay.onReloadResAndMeasure(
-                filterIds = arrayOf(TEST_DECOR_VIEW_ID_2),
-                reloadToken = 1,
-                rotation = Surface.ROTATION_90,
-                displayUniqueId = null)
-        verify(decorProvider1, never()).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_1)!!, 1, Surface.ROTATION_90, null)
-        verify(decorProvider2, times(1)).onReloadResAndMeasure(
-                overlay.getView(TEST_DECOR_VIEW_ID_2)!!, 1, Surface.ROTATION_90, null)
+        Assert.assertNull(overlay.getView(TEST_DECOR_LAYOUT_ID))
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
index 171b767..bac0817 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
@@ -18,6 +18,7 @@
 
 import android.content.res.Resources
 import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
 import android.view.DisplayCutout
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
@@ -31,6 +32,7 @@
 import org.mockito.Mockito.`when` as whenever
 
 @RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
 @SmallTest
 class PrivacyDotDecorProviderFactoryTest : SysuiTestCase() {
     private lateinit var mPrivacyDotDecorProviderFactory: PrivacyDotDecorProviderFactory
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
deleted file mode 100644
index 621bcf6..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
+++ /dev/null
@@ -1,142 +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.systemui.decor
-
-import android.testing.AndroidTestingRunner
-import android.util.Size
-import android.view.DisplayCutout
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import org.junit.Assert
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.spy
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-class RoundedCornerDecorProviderFactoryTest : SysuiTestCase() {
-
-    @Mock private lateinit var roundedCornerResDelegate: RoundedCornerResDelegate
-    private lateinit var roundedCornerDecorProviderFactory: RoundedCornerDecorProviderFactory
-
-    @Before
-    fun setUp() {
-        roundedCornerResDelegate = spy(RoundedCornerResDelegate(mContext.resources, null))
-    }
-
-    @Test
-    fun testNoRoundedCorners() {
-        Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
-        Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
-        Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
-
-        roundedCornerDecorProviderFactory =
-                RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
-
-        Assert.assertEquals(false, roundedCornerDecorProviderFactory.hasProviders)
-        Assert.assertEquals(0, roundedCornerDecorProviderFactory.providers.size)
-    }
-
-    @Test
-    fun testHasRoundedCornersIfTopWidthLargerThan0() {
-        Mockito.doReturn(Size(1, 0)).`when`(roundedCornerResDelegate).topRoundedSize
-        Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).bottomRoundedSize
-        Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
-
-        roundedCornerDecorProviderFactory =
-                RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
-
-        Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
-        roundedCornerDecorProviderFactory.providers.let { providers ->
-            Assert.assertEquals(2, providers.size)
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_top_left)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
-            })
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_top_right)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
-            })
-        }
-    }
-
-    @Test
-    fun testHasRoundedCornersIfBottomWidthLargerThan0() {
-        Mockito.doReturn(Size(0, 0)).`when`(roundedCornerResDelegate).topRoundedSize
-        Mockito.doReturn(Size(1, 1)).`when`(roundedCornerResDelegate).bottomRoundedSize
-        Mockito.doReturn(false).`when`(roundedCornerResDelegate).isMultipleRadius
-
-        roundedCornerDecorProviderFactory =
-                RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
-
-        Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
-        roundedCornerDecorProviderFactory.providers.let { providers ->
-            Assert.assertEquals(2, providers.size)
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_bottom_left)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
-            })
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_bottom_right)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
-            })
-        }
-    }
-
-    @Test
-    fun test4CornerDecorProvidersInfo() {
-        Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).topRoundedSize
-        Mockito.doReturn(Size(10, 10)).`when`(roundedCornerResDelegate).bottomRoundedSize
-        Mockito.doReturn(true).`when`(roundedCornerResDelegate).isMultipleRadius
-
-        roundedCornerDecorProviderFactory =
-                RoundedCornerDecorProviderFactory(roundedCornerResDelegate)
-
-        Assert.assertEquals(true, roundedCornerDecorProviderFactory.hasProviders)
-        roundedCornerDecorProviderFactory.providers.let { providers ->
-            Assert.assertEquals(4, providers.size)
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_top_left)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
-            })
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_top_right)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_TOP)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
-            })
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_bottom_left)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_LEFT))
-            })
-            Assert.assertEquals(1, providers.count {
-                ((it.viewId == R.id.rounded_corner_bottom_right)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_BOTTOM)
-                        and it.alignedBounds.contains(DisplayCutout.BOUNDS_POSITION_RIGHT))
-            })
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
index fb6ff76..b536bfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
@@ -45,7 +45,7 @@
     }
 
     @Test
-    fun testUpdateDisplayUniqueId() {
+    fun testReloadAllAndDefaultRadius() {
         mContext.orCreateTestableResources.addOverrides(
                 mockTypeArray = mockTypedArray,
                 radius = 3,
@@ -65,34 +65,7 @@
                 radiusTop = 6,
                 radiusBottom = 0)
 
-        roundedCornerResDelegate.updateDisplayUniqueId("test", null)
-
-        assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
-        assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
-    }
-
-    @Test
-    fun testNotUpdateDisplayUniqueIdButChangeRefreshToken() {
-        mContext.orCreateTestableResources.addOverrides(
-                mockTypeArray = mockTypedArray,
-                radius = 3,
-                radiusTop = 0,
-                radiusBottom = 4,
-                multipleRadius = false)
-
-        roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
-
-        assertEquals(Size(3, 3), roundedCornerResDelegate.topRoundedSize)
-        assertEquals(Size(4, 4), roundedCornerResDelegate.bottomRoundedSize)
-        assertEquals(false, roundedCornerResDelegate.isMultipleRadius)
-
-        mContext.orCreateTestableResources.addOverrides(
-                mockTypeArray = mockTypedArray,
-                radius = 5,
-                radiusTop = 6,
-                radiusBottom = 0)
-
-        roundedCornerResDelegate.updateDisplayUniqueId(null, 1)
+        roundedCornerResDelegate.reloadAll("test")
 
         assertEquals(Size(6, 6), roundedCornerResDelegate.topRoundedSize)
         assertEquals(Size(5, 5), roundedCornerResDelegate.bottomRoundedSize)
@@ -109,21 +82,11 @@
         roundedCornerResDelegate = RoundedCornerResDelegate(mContext.resources, null)
 
         val factor = 5
-        roundedCornerResDelegate.updateTuningSizeFactor(factor, 1)
+        roundedCornerResDelegate.updateTuningSizeFactor(factor)
         val length = (factor * mContext.resources.displayMetrics.density).toInt()
 
         assertEquals(Size(length, length), roundedCornerResDelegate.topRoundedSize)
         assertEquals(Size(length, length), roundedCornerResDelegate.bottomRoundedSize)
-
-        mContext.orCreateTestableResources.addOverrides(
-                mockTypeArray = mockTypedArray,
-                radiusTop = 1,
-                radiusBottom = 2,
-                multipleRadius = false)
-        roundedCornerResDelegate.updateTuningSizeFactor(null, 2)
-
-        assertEquals(Size(1, 1), roundedCornerResDelegate.topRoundedSize)
-        assertEquals(Size(2, 2), roundedCornerResDelegate.bottomRoundedSize)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
new file mode 100644
index 0000000..c861221
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayNotificationCountProviderTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.systemui.dreams;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class DreamOverlayNotificationCountProviderTest extends SysuiTestCase {
+    @Mock
+    NotificationListener mNotificationListener;
+    @Mock
+    DreamOverlayNotificationCountProvider.Callback mCallback;
+    @Mock
+    StatusBarNotification mNotification1;
+    @Mock
+    StatusBarNotification mNotification2;
+    @Mock
+    NotificationListenerService.RankingMap mRankingMap;
+
+    private DreamOverlayNotificationCountProvider mProvider;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mNotification1.getKey()).thenReturn("key1");
+        when(mNotification2.getKey()).thenReturn("key2");
+
+        final StatusBarNotification[] notifications = {mNotification1};
+        when(mNotificationListener.getActiveNotifications()).thenReturn(notifications);
+        mProvider = new DreamOverlayNotificationCountProvider(mNotificationListener);
+        mProvider.addCallback(mCallback);
+    }
+
+    @Test
+    public void testPostingNotificationCallsCallbackWithNotificationCount() {
+        final ArgumentCaptor<NotificationHandler> handlerArgumentCaptor =
+                ArgumentCaptor.forClass(NotificationHandler.class);
+        verify(mNotificationListener).addNotificationHandler(handlerArgumentCaptor.capture());
+        handlerArgumentCaptor.getValue().onNotificationPosted(mNotification2, mRankingMap);
+        verify(mCallback).onNotificationCountChanged(2);
+    }
+
+    @Test
+    public void testRemovingNotificationCallsCallbackWithZeroNotificationCount() {
+        final ArgumentCaptor<NotificationHandler> handlerArgumentCaptor =
+                ArgumentCaptor.forClass(NotificationHandler.class);
+        verify(mNotificationListener).addNotificationHandler(handlerArgumentCaptor.capture());
+        handlerArgumentCaptor.getValue().onNotificationRemoved(mNotification1, mRankingMap);
+        verify(mCallback).onNotificationCountChanged(0);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index a6921b4..4915ded 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -31,15 +31,12 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.provider.Settings;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -84,13 +81,9 @@
     @Mock
     IndividualSensorPrivacyController mSensorPrivacyController;
     @Mock
-    StatusBarNotification mStatusBarNotification;
-    @Mock
-    NotificationListenerService.RankingMap mRankingMap;
-    @Mock
-    NotificationListener mNotificationListener;
-    @Mock
     ZenModeController mZenModeController;
+    @Mock
+    DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider;
 
     private final Executor mMainExecutor = Runnable::run;
 
@@ -113,7 +106,7 @@
                 mNextAlarmController,
                 mDateFormatUtil,
                 mSensorPrivacyController,
-                mNotificationListener,
+                mDreamOverlayNotificationCountProvider,
                 mZenModeController);
     }
 
@@ -123,6 +116,7 @@
         verify(mNextAlarmController).addCallback(any());
         verify(mSensorPrivacyController).addCallback(any());
         verify(mZenModeController).addCallback(any());
+        verify(mDreamOverlayNotificationCountProvider).addCallback(any());
     }
 
     @Test
@@ -202,17 +196,26 @@
 
     @Test
     public void testOnViewAttachedShowsNotificationsIconWhenNotificationsExist() {
-        StatusBarNotification[] notifications = { mStatusBarNotification };
-        when(mNotificationListener.getActiveNotifications()).thenReturn(notifications);
         mController.onViewAttached();
+
+        final ArgumentCaptor<DreamOverlayNotificationCountProvider.Callback> callbackCapture =
+                ArgumentCaptor.forClass(DreamOverlayNotificationCountProvider.Callback.class);
+        verify(mDreamOverlayNotificationCountProvider).addCallback(callbackCapture.capture());
+        callbackCapture.getValue().onNotificationCountChanged(1);
+
         verify(mView).showIcon(
                 eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
     }
 
     @Test
     public void testOnViewAttachedHidesNotificationsIconWhenNoNotificationsExist() {
-        when(mNotificationListener.getActiveNotifications()).thenReturn(null);
         mController.onViewAttached();
+
+        final ArgumentCaptor<DreamOverlayNotificationCountProvider.Callback> callbackCapture =
+                ArgumentCaptor.forClass(DreamOverlayNotificationCountProvider.Callback.class);
+        verify(mDreamOverlayNotificationCountProvider).addCallback(callbackCapture.capture());
+        callbackCapture.getValue().onNotificationCountChanged(0);
+
         verify(mView).showIcon(
                 eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), isNull());
     }
@@ -248,6 +251,7 @@
         verify(mNextAlarmController).removeCallback(any());
         verify(mSensorPrivacyController).removeCallback(any());
         verify(mZenModeController).removeCallback(any());
+        verify(mDreamOverlayNotificationCountProvider).removeCallback(any());
     }
 
     @Test
@@ -309,13 +313,10 @@
     public void testNotificationsIconShownWhenNotificationAdded() {
         mController.onViewAttached();
 
-        StatusBarNotification[] notifications = { mStatusBarNotification };
-        when(mNotificationListener.getActiveNotifications()).thenReturn(notifications);
-
-        final ArgumentCaptor<NotificationListener.NotificationHandler> callbackCapture =
-                ArgumentCaptor.forClass(NotificationListener.NotificationHandler.class);
-        verify(mNotificationListener).addNotificationHandler(callbackCapture.capture());
-        callbackCapture.getValue().onNotificationPosted(mStatusBarNotification, mRankingMap);
+        final ArgumentCaptor<DreamOverlayNotificationCountProvider.Callback> callbackCapture =
+                ArgumentCaptor.forClass(DreamOverlayNotificationCountProvider.Callback.class);
+        verify(mDreamOverlayNotificationCountProvider).addCallback(callbackCapture.capture());
+        callbackCapture.getValue().onNotificationCountChanged(1);
 
         verify(mView).showIcon(
                 eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
@@ -323,15 +324,12 @@
 
     @Test
     public void testNotificationsIconHiddenWhenLastNotificationRemoved() {
-        StatusBarNotification[] notifications = { mStatusBarNotification };
-        when(mNotificationListener.getActiveNotifications()).thenReturn(notifications)
-                .thenReturn(null);
         mController.onViewAttached();
 
-        final ArgumentCaptor<NotificationListener.NotificationHandler> callbackCapture =
-                ArgumentCaptor.forClass(NotificationListener.NotificationHandler.class);
-        verify(mNotificationListener).addNotificationHandler(callbackCapture.capture());
-        callbackCapture.getValue().onNotificationPosted(mStatusBarNotification, mRankingMap);
+        final ArgumentCaptor<DreamOverlayNotificationCountProvider.Callback> callbackCapture =
+                ArgumentCaptor.forClass(DreamOverlayNotificationCountProvider.Callback.class);
+        verify(mDreamOverlayNotificationCountProvider).addCallback(callbackCapture.capture());
+        callbackCapture.getValue().onNotificationCountChanged(0);
 
         verify(mView).showIcon(
                 eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(false), any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 52c8a55..fc19d13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -255,14 +255,25 @@
     }
 
     @Test
-    fun testDragDownAmount_depthDistanceIsZero_doesNotSetProgress() {
+    fun testDragDownAmount_depthDistanceIsZero_setsProgressToZero() {
         context.getOrCreateTestableResources()
             .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 0)
         configurationController.notifyConfigurationChanged()
 
         transitionController.dragDownAmount = 10f
 
-        verify(depthController, never()).transitionToFullShadeProgress
+        verify(depthController).transitionToFullShadeProgress = 0f
+    }
+
+    @Test
+    fun testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistance() {
+        context.getOrCreateTestableResources()
+            .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
+        configurationController.notifyConfigurationChanged()
+
+        transitionController.dragDownAmount = 10f
+
+        verify(depthController).transitionToFullShadeProgress = 0.1f
     }
 
     @Test
@@ -413,6 +424,28 @@
         verifyZeroInteractions(singleShadeOverScroller)
     }
 
+    @Test
+    fun setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistance() {
+        val alphaDistance = context.resources.getDimensionPixelSize(
+            R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
+        val dragDownAmount = 10f
+        enableSplitShade()
+
+        transitionController.dragDownAmount = dragDownAmount
+
+        val expectedAlpha = 1 - dragDownAmount / alphaDistance
+        verify(notificationPanelController).setKeyguardStatusBarAlpha(expectedAlpha)
+    }
+
+    @Test
+    fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() {
+        disableSplitShade()
+
+        transitionController.dragDownAmount = 10f
+
+        verify(notificationPanelController).setKeyguardStatusBarAlpha(-1f)
+    }
+
     private fun enableSplitShade() {
         setSplitShadeEnabled(true)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
index 32d625c..4e07d59 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
@@ -19,6 +19,7 @@
 import static android.app.Notification.VISIBILITY_PUBLIC;
 import static android.app.Notification.VISIBILITY_SECRET;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 
 import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry;
@@ -209,7 +210,7 @@
         Consumer<String> listener = mock(Consumer.class);
         mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
 
-        mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, true);
 
         verify(listener).accept(anyString());
     }
@@ -220,7 +221,7 @@
         Consumer<String> listener = mock(Consumer.class);
         mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
 
-        mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1);
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, true);
 
         verify(listener).accept(anyString());
     }
@@ -231,7 +232,7 @@
         Consumer<String> listener = mock(Consumer.class);
         mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
 
-        mFakeSettings.putInt(Settings.Global.ZEN_MODE, 1);
+        mFakeSettings.putBool(Settings.Global.ZEN_MODE, true);
 
         verify(listener).accept(anyString());
     }
@@ -242,7 +243,7 @@
         Consumer<String> listener = mock(Consumer.class);
         mKeyguardNotificationVisibilityProvider.addOnStateChangedListener(listener);
 
-        mFakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, true);
 
         verify(listener).accept(anyString());
     }
@@ -338,6 +339,25 @@
     }
 
     @Test
+    public void showSilentOnLockscreenSetting() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState(mEntry);
+
+        // WHEN the notification is not high priority and not ambient
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setImportance(IMPORTANCE_LOW)
+                .build());
+        when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false);
+
+        // WHEN the show silent notifs on lockscreen setting is true
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, true);
+
+        // THEN do not filter out the entry
+        assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry));
+    }
+
+    @Test
     public void summaryExceedsThresholdToShow() {
         // GIVEN the notification doesn't exceed the threshold to show on the lockscreen
         // but it's part of a group (has a parent)
@@ -360,6 +380,7 @@
                 .build());
 
         // WHEN its parent does exceed threshold tot show on the lockscreen
+        mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, false);
         when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true);
 
         // THEN don't filter out the entry
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index 7de3545..39d5a16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -343,6 +343,28 @@
         assertThat(mKeyguardStatusBarView.getVisibility()).isEqualTo(View.INVISIBLE);
     }
 
+    @Test
+    public void setAlpha_explicitAlpha_setsExplicitAlpha() {
+        mController.onViewAttached();
+        updateStateToKeyguard();
+
+        mController.setAlpha(0.5f);
+
+        assertThat(mKeyguardStatusBarView.getAlpha()).isEqualTo(0.5f);
+    }
+
+    @Test
+    public void setAlpha_explicitAlpha_thenMinusOneAlpha_setsAlphaBasedOnDefaultCriteria() {
+        mController.onViewAttached();
+        updateStateToKeyguard();
+
+        mController.setAlpha(0.5f);
+        mController.setAlpha(-1f);
+
+        assertThat(mKeyguardStatusBarView.getAlpha()).isGreaterThan(0);
+        assertThat(mKeyguardStatusBarView.getAlpha()).isNotEqualTo(0.5f);
+    }
+
     // TODO(b/195442899): Add more tests for #updateViewState once CLs are finalized.
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 5add2f2..22bf6c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -938,6 +938,15 @@
         verify(mScrimController).setExpansionAffectsAlpha(true);
     }
 
+    @Test
+    public void setKeyguardStatusBarAlpha_setsAlphaOnKeyguardStatusBarController() {
+        float statusBarAlpha = 0.5f;
+
+        mNotificationPanelViewController.setKeyguardStatusBarAlpha(statusBarAlpha);
+
+        verify(mKeyguardStatusBarViewController).setAlpha(statusBarAlpha);
+    }
+
     private void triggerPositionClockAndNotifications() {
         mNotificationPanelViewController.closeQs();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 134ad4b..f0a6e40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1078,8 +1078,9 @@
                 ScrimState.OFF, ScrimState.AOD, ScrimState.PULSING));
         HashSet<ScrimState> regularStates = new HashSet<>(Arrays.asList(
                 ScrimState.UNINITIALIZED, ScrimState.KEYGUARD, ScrimState.BOUNCER,
-                ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR, ScrimState.UNLOCKED,
-                ScrimState.SHADE_LOCKED, ScrimState.AUTH_SCRIMMED, ScrimState.AUTH_SCRIMMED_SHADE));
+                ScrimState.DREAMING, ScrimState.BOUNCER_SCRIMMED, ScrimState.BRIGHTNESS_MIRROR,
+                ScrimState.UNLOCKED, ScrimState.SHADE_LOCKED, ScrimState.AUTH_SCRIMMED,
+                ScrimState.AUTH_SCRIMMED_SHADE));
 
         for (ScrimState state : ScrimState.values()) {
             if (!lowPowerModeStates.contains(state) && !regularStates.contains(state)) {
@@ -1107,6 +1108,7 @@
         // GIVEN device has an activity showing ('UNLOCKED' state can occur on the lock screen
         // with the camera app occluding the keyguard)
         mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.setClipsQsScrim(true);
         mScrimController.setRawPanelExpansionFraction(1);
         // notifications scrim alpha change require calling setQsPosition
         mScrimController.setQsPosition(0, 300);
@@ -1120,6 +1122,12 @@
                 mScrimBehind.getViewAlpha(), 1, 0.0);
         assertEquals("Notifications scrim should be opaque",
                 mNotificationsScrim.getViewAlpha(), 1, 0.0);
+
+        assertScrimTinted(Map.of(
+                mScrimInFront, true,
+                mScrimBehind, true,
+                mNotificationsScrim, false
+        ));
     }
 
     @Test
@@ -1323,6 +1331,25 @@
         assertThat(mScrimInFront.getTranslationY()).isEqualTo(0);
     }
 
+    @Test
+    public void transitionToDreaming() {
+        mScrimController.setRawPanelExpansionFraction(0f);
+        mScrimController.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN);
+        mScrimController.transitionTo(ScrimState.DREAMING);
+        finishAnimationsImmediately();
+
+        assertScrimAlpha(Map.of(
+                mScrimInFront, TRANSPARENT,
+                mNotificationsScrim, TRANSPARENT,
+                mScrimBehind, TRANSPARENT));
+
+        assertScrimTinted(Map.of(
+                mScrimInFront, false,
+                mScrimBehind, true,
+                mNotificationsScrim, false
+        ));
+    }
+
     private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
         mScrimController.setRawPanelExpansionFraction(expansion);
         finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
new file mode 100644
index 0000000..5509a6ca
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -0,0 +1,221 @@
+/*
+ * 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.systemui.unfold.progress
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
+import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
+import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
+import com.android.systemui.unfold.util.TestFoldStateProvider
+import com.android.systemui.util.leak.ReferenceTestUtils.waitForCondition
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class PhysicsBasedUnfoldTransitionProgressProviderTest : SysuiTestCase() {
+
+    private val foldStateProvider: TestFoldStateProvider = TestFoldStateProvider()
+    private val listener = TestUnfoldProgressListener()
+    private lateinit var progressProvider: UnfoldTransitionProgressProvider
+
+    @Before
+    fun setUp() {
+        progressProvider = PhysicsBasedUnfoldTransitionProgressProvider(
+            foldStateProvider
+        )
+        progressProvider.addCallback(listener)
+    }
+
+    @Test
+    fun testUnfold_emitsIncreasingTransitionEvents() {
+        runOnMainThreadWithInterval(
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendHingeAngleUpdate(90f) },
+            { foldStateProvider.sendHingeAngleUpdate(180f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
+        )
+
+        with(listener.ensureTransitionFinished()) {
+            assertIncreasingProgress()
+            assertFinishedWithUnfold()
+        }
+    }
+
+    @Test
+    fun testUnfold_screenAvailableOnlyAfterFullUnfold_emitsIncreasingTransitionEvents() {
+        runOnMainThreadWithInterval(
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendHingeAngleUpdate(90f) },
+            { foldStateProvider.sendHingeAngleUpdate(180f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+        )
+
+        with(listener.ensureTransitionFinished()) {
+            assertIncreasingProgress()
+            assertFinishedWithUnfold()
+        }
+    }
+
+    @Test
+    fun testFold_emitsDecreasingTransitionEvents() {
+        runOnMainThreadWithInterval(
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_CLOSING) },
+            { foldStateProvider.sendHingeAngleUpdate(170f) },
+            { foldStateProvider.sendHingeAngleUpdate(90f) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
+        )
+
+        with(listener.ensureTransitionFinished()) {
+            assertDecreasingProgress()
+            assertFinishedWithFold()
+        }
+    }
+
+    @Test
+    fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
+        runOnMainThreadWithInterval(
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendHingeAngleUpdate(90f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
+        )
+
+        with(listener.ensureTransitionFinished()) {
+            assertIncreasingProgress()
+            assertFinishedWithUnfold()
+        }
+    }
+
+    @Test
+    fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
+        runOnMainThreadWithInterval(
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendHingeAngleUpdate(90f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_CLOSING) },
+            { foldStateProvider.sendHingeAngleUpdate(60f) },
+            { foldStateProvider.sendHingeAngleUpdate(10f) },
+            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_CLOSED) },
+        )
+
+        with(listener.ensureTransitionFinished()) {
+            assertHasFoldAnimationAtTheEnd()
+        }
+    }
+
+    private class TestUnfoldProgressListener : TransitionProgressListener {
+
+        private val recordings: MutableList<UnfoldTransitionRecording> = arrayListOf()
+        private var currentRecording: UnfoldTransitionRecording? = null
+
+        override fun onTransitionStarted() {
+            assertWithMessage("Trying to start a transition when it is already in progress")
+                .that(currentRecording).isNull()
+
+            currentRecording = UnfoldTransitionRecording()
+        }
+
+        override fun onTransitionProgress(progress: Float) {
+            assertWithMessage("Received transition progress event when it's not started")
+                .that(currentRecording).isNotNull()
+            currentRecording!!.addProgress(progress)
+        }
+
+        override fun onTransitionFinished() {
+            assertWithMessage("Received transition finish event when it's not started")
+                .that(currentRecording).isNotNull()
+            recordings += currentRecording!!
+            currentRecording = null
+        }
+
+        fun ensureTransitionFinished(): UnfoldTransitionRecording {
+            waitForCondition { recordings.size == 1 }
+            return recordings.first()
+        }
+
+        class UnfoldTransitionRecording {
+            private val progressHistory: MutableList<Float> = arrayListOf()
+
+            fun addProgress(progress: Float) {
+                assertThat(progress).isAtMost(1.0f)
+                assertThat(progress).isAtLeast(0.0f)
+
+                progressHistory += progress
+            }
+
+            fun assertIncreasingProgress() {
+                assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
+                assertThat(progressHistory).isInOrder()
+            }
+
+            fun assertDecreasingProgress() {
+                assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
+                assertThat(progressHistory).isInOrder(Comparator.reverseOrder<Float>())
+            }
+
+            fun assertFinishedWithUnfold() {
+                assertThat(progressHistory).isNotEmpty()
+                assertThat(progressHistory.last()).isEqualTo(1.0f)
+            }
+
+            fun assertFinishedWithFold() {
+                assertThat(progressHistory).isNotEmpty()
+                assertThat(progressHistory.last()).isEqualTo(0.0f)
+            }
+
+            fun assertHasFoldAnimationAtTheEnd() {
+                // Check that there are at least a few decreasing events at the end
+                assertThat(progressHistory.size).isGreaterThan(MIN_ANIMATION_EVENTS)
+                assertThat(progressHistory.takeLast(MIN_ANIMATION_EVENTS))
+                    .isInOrder(Comparator.reverseOrder<Float>())
+                assertThat(progressHistory.last()).isEqualTo(0.0f)
+            }
+        }
+
+        private companion object {
+            private const val MIN_ANIMATION_EVENTS = 5
+        }
+    }
+
+    private fun runOnMainThreadWithInterval(vararg blocks: () -> Unit, intervalMillis: Long = 60) {
+        blocks.forEach {
+            InstrumentationRegistry.getInstrumentation().runOnMainSync {
+                it()
+            }
+            Thread.sleep(intervalMillis)
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index f43dc6c..7ac2434 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -16,6 +16,11 @@
 
 package com.android.systemui.unfold.updates
 
+import android.app.ActivityManager
+import android.app.ActivityManager.RunningTaskInfo
+import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.ActivityType
 import android.hardware.devicestate.DeviceStateManager
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener
 import android.os.Handler
@@ -30,7 +35,6 @@
 import com.android.systemui.unfold.util.FoldableTestUtils
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
-import java.lang.Exception
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -51,6 +55,8 @@
 
     @Mock private lateinit var deviceStateManager: DeviceStateManager
 
+    @Mock private lateinit var activityManager: ActivityManager
+
     @Mock private lateinit var handler: Handler
 
     @Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
@@ -80,6 +86,7 @@
                 hingeAngleProvider,
                 screenStatusProvider,
                 deviceStateManager,
+                activityManager,
                 context.mainExecutor,
                 handler)
 
@@ -113,6 +120,9 @@
             }
             null
         }
+
+        // By default, we're on launcher.
+        setupForegroundActivityType(ACTIVITY_TYPE_HOME)
     }
 
     @Test
@@ -258,6 +268,31 @@
         }
     }
 
+    @Test
+    fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
+        setupForegroundActivityType(ACTIVITY_TYPE_STANDARD)
+        sendHingeAngleEvent(180)
+
+        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
+
+        assertThat(foldUpdates).isEmpty()
+    }
+
+    @Test
+    fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
+        setupForegroundActivityType(ACTIVITY_TYPE_STANDARD)
+        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+
+        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    private fun setupForegroundActivityType(@ActivityType type: Int) {
+        val taskInfo = RunningTaskInfo().apply { topActivityType = type }
+        whenever(activityManager.getRunningTasks(1)).thenReturn(listOf(taskInfo))
+    }
+
     private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
         val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.")
         if (waitTime >= runnableDelay) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
new file mode 100644
index 0000000..dd307b4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.systemui.unfold.util
+
+import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
+import com.android.systemui.unfold.updates.FoldStateProvider
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
+import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
+
+class TestFoldStateProvider : FoldStateProvider {
+
+    private val listeners: MutableList<FoldUpdatesListener> = arrayListOf()
+
+    override fun start() {
+    }
+
+    override fun stop() {
+        listeners.clear()
+    }
+
+    private var _isFullyOpened: Boolean = false
+
+    override val isFullyOpened: Boolean
+        get() = _isFullyOpened
+
+    override fun addCallback(listener: FoldUpdatesListener) {
+        listeners += listener
+    }
+
+    override fun removeCallback(listener: FoldUpdatesListener) {
+        listeners -= listener
+    }
+
+    fun sendFoldUpdate(@FoldUpdate update: Int) {
+        if (update == FOLD_UPDATE_FINISH_FULL_OPEN) {
+            _isFullyOpened = true
+        }
+        listeners.forEach { it.onFoldUpdate(update) }
+    }
+
+    fun sendHingeAngleUpdate(angle: Float) {
+        listeners.forEach { it.onHingeAngleUpdate(angle) }
+    }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
index 51e01ea..6114213 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityTraceManager.java
@@ -50,7 +50,7 @@
     private final AccessibilityManagerService mService;
     private final Object mA11yMSLock;
 
-    private long mEnabledLoggingFlags;
+    private volatile long mEnabledLoggingFlags;
 
     private static AccessibilityTraceManager sInstance = null;
 
@@ -77,34 +77,28 @@
 
     @Override
     public boolean isA11yTracingEnabled() {
-        synchronized (mA11yMSLock) {
-            return mEnabledLoggingFlags != FLAGS_LOGGING_NONE;
-        }
+        return mEnabledLoggingFlags != FLAGS_LOGGING_NONE;
     }
 
     @Override
     public boolean isA11yTracingEnabledForTypes(long typeIdFlags) {
-        synchronized (mA11yMSLock) {
-            return ((typeIdFlags & mEnabledLoggingFlags) != FLAGS_LOGGING_NONE);
-        }
+        return ((typeIdFlags & mEnabledLoggingFlags) != FLAGS_LOGGING_NONE);
     }
 
     @Override
     public int getTraceStateForAccessibilityManagerClientState() {
         int state = 0x0;
-        synchronized (mA11yMSLock) {
-            if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION)) {
-                state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED;
-            }
-            if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION_CALLBACK)) {
-                state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED;
-            }
-            if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CLIENT)) {
-                state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED;
-            }
-            if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE)) {
-                state |= STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED;
-            }
+        if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION)) {
+            state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_ENABLED;
+        }
+        if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION_CALLBACK)) {
+            state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CONNECTION_CB_ENABLED;
+        }
+        if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CLIENT)) {
+            state |= STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED;
+        }
+        if (isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE)) {
+            state |= STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED;
         }
         return state;
     }
@@ -116,11 +110,11 @@
             return;
         }
 
-        synchronized (mA11yMSLock) {
-            long oldEnabled = mEnabledLoggingFlags;
-            mEnabledLoggingFlags = loggingTypes;
+        long oldEnabled = mEnabledLoggingFlags;
+        mEnabledLoggingFlags = loggingTypes;
 
-            if (needToNotifyClients(oldEnabled)) {
+        if (needToNotifyClients(oldEnabled)) {
+            synchronized (mA11yMSLock) {
                 mService.scheduleUpdateClientsIfNeededLocked(mService.getCurrentUserState());
             }
         }
@@ -130,14 +124,14 @@
 
     @Override
     public void stopTrace() {
-        boolean stop = false;
-        synchronized (mA11yMSLock) {
-            stop = isA11yTracingEnabled();
+        boolean stop;
+        stop = isA11yTracingEnabled();
 
-            long oldEnabled = mEnabledLoggingFlags;
-            mEnabledLoggingFlags = FLAGS_LOGGING_NONE;
+        long oldEnabled = mEnabledLoggingFlags;
+        mEnabledLoggingFlags = FLAGS_LOGGING_NONE;
 
-            if (needToNotifyClients(oldEnabled)) {
+        if (needToNotifyClients(oldEnabled)) {
+            synchronized (mA11yMSLock) {
                 mService.scheduleUpdateClientsIfNeededLocked(mService.getCurrentUserState());
             }
         }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 51b49ed..55dc196 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -37,6 +37,7 @@
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.RemoteCallbackList;
 import android.provider.Settings;
@@ -123,8 +124,8 @@
     private int mInteractiveUiTimeout = 0;
     private int mLastSentClientState = -1;
 
-    /** {@code true} if the device config supports magnification area. */
-    private final boolean mSupportMagnificationArea;
+    /** {@code true} if the device config supports window magnification. */
+    private final boolean mSupportWindowMagnification;
     // The magnification modes on displays.
     private final SparseIntArray mMagnificationModes = new SparseIntArray();
     // The magnification capabilities used to know magnification mode could be switched.
@@ -148,7 +149,7 @@
 
     boolean isValidMagnificationModeLocked(int displayId) {
         final int mode = getMagnificationModeLocked(displayId);
-        if (!mSupportMagnificationArea
+        if (!mSupportWindowMagnification
                 && mode == Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
             return false;
         }
@@ -170,8 +171,9 @@
                 R.color.accessibility_focus_highlight_color);
         mFocusStrokeWidth = mFocusStrokeWidthDefaultValue;
         mFocusColor = mFocusColorDefaultValue;
-        mSupportMagnificationArea = mContext.getResources().getBoolean(
-                R.bool.config_magnification_area);
+        mSupportWindowMagnification = mContext.getResources().getBoolean(
+                R.bool.config_magnification_area) && mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WINDOW_MAGNIFICATION);
     }
 
     boolean isHandlingAccessibilityEventsLocked() {
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index 3a26c46..f4c24a8 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -165,7 +165,10 @@
 
     @Override
     public void onTopActivityChanged(ComponentName topActivity, int uid) {
-        if (mActivityListener != null) {
+        // Don't send onTopActivityChanged() callback when topActivity is null because it's defined
+        // as @NonNull in ActivityListener interface. Sends onDisplayEmpty() callback instead when
+        // there is no activity running on virtual display.
+        if (mActivityListener != null && topActivity != null) {
             // Post callback on the main thread so it doesn't block activity launching
             mHandler.post(() ->
                     mActivityListener.onTopActivityChanged(Display.INVALID_DISPLAY, topActivity));
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index b05a7db..06fd5c0 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -173,6 +173,11 @@
         return flags;
     }
 
+    /** Returns the device display name. */
+    CharSequence getDisplayName() {
+        return mAssociationInfo.getDisplayName();
+    }
+
     @Override // Binder call
     public int getAssociationId() {
         return mAssociationInfo.getId();
@@ -523,8 +528,7 @@
             }
             PowerManager powerManager = mContext.getSystemService(PowerManager.class);
             PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
-                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                            | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                     TAG + ":" + displayId, displayId);
             wakeLock.acquire();
             mPerDisplayWakelocks.put(displayId, wakeLock);
@@ -596,6 +600,13 @@
      * Shows a toast on virtual displays owned by this device which have a given uid running.
      */
     void showToastWhereUidIsRunning(int uid, @StringRes int resId, @Toast.Duration int duration) {
+        showToastWhereUidIsRunning(uid, mContext.getString(resId), duration);
+    }
+
+    /**
+     * Shows a toast on virtual displays owned by this device which have a given uid running.
+     */
+    void showToastWhereUidIsRunning(int uid, String text, @Toast.Duration int duration) {
         synchronized (mVirtualDeviceLock) {
             DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
             final int size = mWindowPolicyControllers.size();
@@ -604,7 +615,7 @@
                     int displayId = mWindowPolicyControllers.keyAt(i);
                     Display display = displayManager.getDisplay(displayId);
                     if (display != null && display.isValid()) {
-                        Toast.makeText(mContext.createDisplayContext(display), resId,
+                        Toast.makeText(mContext.createDisplayContext(display), text,
                                 duration).show();
                     }
                 }
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index 9f252d7..96400c1 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -193,8 +193,12 @@
         synchronized (mVirtualDeviceManagerLock) {
             int size = mVirtualDevices.size();
             for (int i = 0; i < size; i++) {
+                CharSequence deviceName = mVirtualDevices.valueAt(i).getDisplayName();
                 mVirtualDevices.valueAt(i).showToastWhereUidIsRunning(appUid,
-                        com.android.internal.R.string.vdm_camera_access_denied, Toast.LENGTH_LONG);
+                        getContext().getString(
+                            com.android.internal.R.string.vdm_camera_access_denied,
+                            deviceName),
+                        Toast.LENGTH_LONG);
             }
         }
     }
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 593c406..59db686 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -129,15 +129,15 @@
 
         @Override
         public void sendMessage(int subId, String callingPkg, Uri contentUri, String locationUrl,
-                Bundle configOverrides, PendingIntent sentIntent, long messageId)
-                throws RemoteException {
+                Bundle configOverrides, PendingIntent sentIntent, long messageId,
+                String attributionTag) throws RemoteException {
             returnPendingIntentWithError(sentIntent);
         }
 
         @Override
         public void downloadMessage(int subId, String callingPkg, String locationUrl,
                 Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent,
-                long messageId)
+                long messageId, String attributionTag)
                 throws RemoteException {
             returnPendingIntentWithError(downloadedIntent);
         }
@@ -333,12 +333,12 @@
         @Override
         public void sendMessage(int subId, String callingPkg, Uri contentUri,
                 String locationUrl, Bundle configOverrides, PendingIntent sentIntent,
-                long messageId)
+                long messageId, String attributionTag)
                 throws RemoteException {
             Slog.d(TAG, "sendMessage() by " + callingPkg);
             mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) {
                 Slog.e(TAG, callingPkg + " is not allowed to call sendMessage()");
                 return;
             }
@@ -347,18 +347,18 @@
                     Intent.FLAG_GRANT_READ_URI_PERMISSION,
                     subId);
             getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
-                    configOverrides, sentIntent, messageId);
+                    configOverrides, sentIntent, messageId, attributionTag);
         }
 
         @Override
         public void downloadMessage(int subId, String callingPkg, String locationUrl,
-                Uri contentUri, Bundle configOverrides,
-                PendingIntent downloadedIntent, long messageId) throws RemoteException {
+                Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent,
+                long messageId, String attributionTag) throws RemoteException {
             Slog.d(TAG, "downloadMessage() by " + callingPkg);
             mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
                     "Download MMS message");
             if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, attributionTag, null) != AppOpsManager.MODE_ALLOWED) {
                 Slog.e(TAG, callingPkg + " is not allowed to call downloadMessage()");
                 return;
             }
@@ -368,14 +368,14 @@
                     subId);
 
             getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
-                    configOverrides, downloadedIntent, messageId);
+                    configOverrides, downloadedIntent, messageId, attributionTag);
         }
 
         @Override
         public Uri importTextMessage(String callingPkg, String address, int type, String text,
                 long timestampMillis, boolean seen, boolean read) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 // Silently fail AppOps failure due to not being the default SMS app
                 // while writing the TelephonyProvider
                 return FAKE_SMS_SENT_URI;
@@ -389,7 +389,7 @@
                 String messageId, long timestampSecs, boolean seen, boolean read)
                 throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 // Silently fail AppOps failure due to not being the default SMS app
                 // while writing the TelephonyProvider
                 return FAKE_MMS_SENT_URI;
@@ -402,7 +402,7 @@
         public boolean deleteStoredMessage(String callingPkg, Uri messageUri)
                 throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
             return getServiceGuarded().deleteStoredMessage(callingPkg, messageUri);
@@ -412,7 +412,7 @@
         public boolean deleteStoredConversation(String callingPkg, long conversationId)
                 throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
             return getServiceGuarded().deleteStoredConversation(callingPkg, conversationId);
@@ -422,7 +422,7 @@
         public boolean updateStoredMessageStatus(String callingPkg, Uri messageUri,
                 ContentValues statusValues) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
             return getServiceGuarded()
@@ -433,7 +433,7 @@
         public boolean archiveStoredConversation(String callingPkg, long conversationId,
                 boolean archived) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
             return getServiceGuarded()
@@ -444,7 +444,7 @@
         public Uri addTextMessageDraft(String callingPkg, String address, String text)
                 throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 // Silently fail AppOps failure due to not being the default SMS app
                 // while writing the TelephonyProvider
                 return FAKE_SMS_DRAFT_URI;
@@ -456,7 +456,7 @@
         public Uri addMultimediaMessageDraft(String callingPkg, Uri contentUri)
                 throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 // Silently fail AppOps failure due to not being the default SMS app
                 // while writing the TelephonyProvider
                 return FAKE_MMS_DRAFT_URI;
@@ -468,7 +468,7 @@
         public void sendStoredMessage(int subId, String callingPkg, Uri messageUri,
                 Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
             getServiceGuarded().sendStoredMessage(subId, callingPkg, messageUri, configOverrides,
@@ -478,7 +478,7 @@
         @Override
         public void setAutoPersisting(String callingPkg, boolean enabled) throws RemoteException {
             if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
-                    callingPkg) != AppOpsManager.MODE_ALLOWED) {
+                    callingPkg, null, null) != AppOpsManager.MODE_ALLOWED) {
                 return;
             }
             getServiceGuarded().setAutoPersisting(callingPkg, enabled);
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/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index b6b3618..24e5de9 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -1,9 +1,6 @@
 {
     "presubmit": [
         {
-            "name": "CtsLocationFineTestCases"
-        },
-        {
             "name": "CtsLocationCoarseTestCases"
         },
         {
@@ -64,5 +61,10 @@
             ],
             "file_patterns": ["ClipboardService\\.java"]
         }
+    ],
+    "postsubmit": [
+        {
+            "name": "CtsLocationFineTestCases"
+        }
     ]
 }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2643bed..2c0514d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2894,6 +2894,12 @@
                 s.isNotAppComponentUsage = true;
             }
 
+            if (s.app != null && s.app.mState != null
+                    && s.app.mState.getCurProcState() <= PROCESS_STATE_TOP
+                    && (flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+                s.lastTopAlmostPerceptibleBindRequestUptimeMs = SystemClock.uptimeMillis();
+            }
+
             if (s.app != null) {
                 updateServiceClientActivitiesLocked(s.app.mServices, c, true);
             }
@@ -4798,6 +4804,10 @@
             if ((c.flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
                 s.updateIsAllowedBgActivityStartsByBinding();
             }
+            // And for almost perceptible exceptions.
+            if ((c.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+                psr.updateHasTopStartedAlmostPerceptibleServices();
+            }
             if (s.app != null) {
                 updateServiceClientActivitiesLocked(s.app.mServices, c, true);
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 39a670e..af9e410 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -108,6 +108,8 @@
     static final String KEY_PROCESS_START_ASYNC = "process_start_async";
     static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
     static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
+    static final String KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
+            "top_to_almost_perceptible_grace_duration";
     static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold";
     static final String KEY_MIN_CRASH_INTERVAL = "min_crash_interval";
     static final String KEY_PROCESS_CRASH_COUNT_RESET_INTERVAL =
@@ -170,6 +172,7 @@
     private static final boolean DEFAULT_PROCESS_START_ASYNC = true;
     private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
     private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
+    private static final long DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION = 15 * 1000;
     private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
     private static final int DEFAULT_MIN_CRASH_INTERVAL = 2 * 60 * 1000;
     private static final int DEFAULT_MAX_PHANTOM_PROCESSES = 32;
@@ -223,6 +226,8 @@
 
     private static final int DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS = 10 * 1000;
 
+    private static final long DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS = 15 * 1000;
+
     // Flag stored in the DeviceConfig API.
     /**
      * Maximum number of cached processes.
@@ -321,6 +326,9 @@
     private static final String KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS =
             "service_start_foreground_anr_delay_ms";
 
+    private static final String KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS =
+            "service_bind_almost_perceptible_timeout_ms";
+
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
 
@@ -464,6 +472,13 @@
     public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
 
     /**
+     * Allow app just leaving TOP with an already running ALMOST_PERCEPTIBLE service to stay in
+     * a higher adj value for this long.
+     */
+    public long TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION =
+            DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION;
+
+    /**
      * The minimum time we allow between crashes, for us to consider this
      * application to be bad and stop its services and reject broadcasts.
      * A reasonable interval here would be anything between 1-3 minutes.
@@ -654,6 +669,13 @@
             DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS;
 
     /**
+     * How long the grace period is from starting an almost perceptible service to a successful
+     * binding before we stop considering it an almost perceptible service.
+     */
+    volatile long mServiceBindAlmostPerceptibleTimeoutMs =
+            DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS;
+
+    /**
      * Defines component aliases. Format
      * ComponentName ":" ComponentName ( "," ComponentName ":" ComponentName )*
      */
@@ -942,6 +964,9 @@
                             case KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS:
                                 updateServiceStartForegroundAnrDealyMs();
                                 break;
+                            case KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS:
+                                updateServiceBindAlmostPerceptibleTimeoutMs();
+                                break;
                             case KEY_NO_KILL_CACHED_PROCESSES_UNTIL_BOOT_COMPLETED:
                                 updateNoKillCachedProcessesUntilBootCompleted();
                                 break;
@@ -1170,6 +1195,9 @@
                     DEFAULT_MEMORY_INFO_THROTTLE_TIME);
             TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
                     DEFAULT_TOP_TO_FGS_GRACE_DURATION);
+            TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION = mParser.getDurationMillis(
+                    KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION,
+                    DEFAULT_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION);
             MIN_CRASH_INTERVAL = mParser.getInt(KEY_MIN_CRASH_INTERVAL,
                     DEFAULT_MIN_CRASH_INTERVAL);
             PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD,
@@ -1432,6 +1460,14 @@
                 DEFAULT_SERVICE_START_FOREGROUND_ANR_DELAY_MS);
     }
 
+    private void updateServiceBindAlmostPerceptibleTimeoutMs() {
+        mServiceBindAlmostPerceptibleTimeoutMs = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS,
+                DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS);
+    }
+
+
     private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
         final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 key, null);
@@ -1647,6 +1683,8 @@
         pw.println(MEMORY_INFO_THROTTLE_TIME);
         pw.print("  "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
         pw.println(TOP_TO_FGS_GRACE_DURATION);
+        pw.print("  "); pw.print(KEY_TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION); pw.print("=");
+        pw.println(TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION);
         pw.print("  "); pw.print(KEY_MIN_CRASH_INTERVAL); pw.print("=");
         pw.println(MIN_CRASH_INTERVAL);
         pw.print("  "); pw.print(KEY_PROCESS_CRASH_COUNT_RESET_INTERVAL); pw.print("=");
@@ -1716,6 +1754,8 @@
         pw.print("="); pw.println(mServiceStartForegroundTimeoutMs);
         pw.print("  "); pw.print(KEY_SERVICE_START_FOREGROUND_ANR_DELAY_MS);
         pw.print("="); pw.println(mServiceStartForegroundAnrDelayMs);
+        pw.print("  "); pw.print(KEY_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS);
+        pw.print("="); pw.println(mServiceBindAlmostPerceptibleTimeoutMs);
 
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f27ccb76..c45b9f2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12945,7 +12945,12 @@
     public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
             String callerFeatureId, String receiverId, IIntentReceiver receiver,
             IntentFilter filter, String permission, int userId, int flags) {
-        enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+        // Allow Sandbox process to register only unexported receivers.
+        if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
+            enforceNotIsolatedCaller("registerReceiver");
+        } else {
+            enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+        }
         ArrayList<Intent> stickyIntents = null;
         ProcessRecord callerApp = null;
         final boolean visibleToInstantApps
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d635152..02206ff 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1674,6 +1674,24 @@
             }
         }
 
+        // If the app was recently in the foreground and has expedited jobs running,
+        // allow it to get a higher rank in memory for some time, compared to other EJS and even
+        // foreground services so that it can finish performing any persistence/processing of
+        // in-memory state.
+        if (psr.hasTopStartedAlmostPerceptibleServices()
+                && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ
+                && (state.getLastTopTime()
+                        + mConstants.TOP_TO_ALMOST_PERCEPTIBLE_GRACE_DURATION > now
+                || state.getSetProcState() <= PROCESS_STATE_TOP)) {
+            adj = ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
+            // This shall henceforth be called the "EJ" exemption, despite utilizing the
+            // ALMOST_PERCEPTIBLE flag to work.
+            state.setAdjType("top-ej-act");
+            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
+                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to recent fg for EJ: " + app);
+            }
+        }
+
         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                 || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) {
             if (state.getForcingToImportant() != null) {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 8f77b87..6b748193 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.IBinder;
+import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
@@ -42,6 +43,18 @@
     private boolean mHasForegroundServices;
 
     /**
+     * Running any services that are almost perceptible (started with
+     * {@link Context#BIND_ALMOST_PERCEPTIBLE} while the app was on TOP)?
+     */
+    private boolean mHasTopStartedAlmostPerceptibleServices;
+
+    /**
+     * The latest value of {@link ServiceRecord#lastTopAlmostPerceptibleBindRequestUptimeMs} among
+     * the currently running services.
+     */
+    private long mLastTopStartedAlmostPerceptibleBindRequestUptimeMs;
+
+    /**
      * Service that applied current connectionGroup/Importance.
      */
     private ServiceRecord mConnectionService;
@@ -146,6 +159,46 @@
         mRepFgServiceTypes = foregroundServiceTypes;
     }
 
+    void updateHasTopStartedAlmostPerceptibleServices() {
+        mHasTopStartedAlmostPerceptibleServices = false;
+        mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = 0;
+        for (int s = mServices.size() - 1; s >= 0; --s) {
+            final ServiceRecord sr = mServices.valueAt(s);
+            mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = Math.max(
+                    mLastTopStartedAlmostPerceptibleBindRequestUptimeMs,
+                    sr.lastTopAlmostPerceptibleBindRequestUptimeMs);
+            if (!mHasTopStartedAlmostPerceptibleServices && isAlmostPerceptible(sr)) {
+                mHasTopStartedAlmostPerceptibleServices = true;
+            }
+        }
+    }
+
+    private boolean isAlmostPerceptible(ServiceRecord record) {
+        if (record.lastTopAlmostPerceptibleBindRequestUptimeMs <= 0) {
+            return false;
+        }
+        final ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
+                record.getConnections();
+        for (int m = serviceConnections.size() - 1; m >= 0; --m) {
+            final ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(m);
+
+            for (int c = clist.size() - 1; c >= 0; --c) {
+                final ConnectionRecord cr = clist.get(c);
+                if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    boolean hasTopStartedAlmostPerceptibleServices() {
+        return mHasTopStartedAlmostPerceptibleServices
+                || (mLastTopStartedAlmostPerceptibleBindRequestUptimeMs > 0
+                && SystemClock.uptimeMillis() - mLastTopStartedAlmostPerceptibleBindRequestUptimeMs
+                < mService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs);
+    }
+
     ServiceRecord getConnectionService() {
         return mConnectionService;
     }
@@ -243,6 +296,14 @@
         if (added && record.serviceInfo != null) {
             mApp.getWindowProcessController().onServiceStarted(record.serviceInfo);
         }
+        if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
+            mLastTopStartedAlmostPerceptibleBindRequestUptimeMs = Math.max(
+                    mLastTopStartedAlmostPerceptibleBindRequestUptimeMs,
+                    record.lastTopAlmostPerceptibleBindRequestUptimeMs);
+            if (!mHasTopStartedAlmostPerceptibleServices) {
+                mHasTopStartedAlmostPerceptibleServices = isAlmostPerceptible(record);
+            }
+        }
         return added;
     }
 
@@ -253,7 +314,11 @@
      * @return true if the service was removed, false otherwise.
      */
     boolean stopService(ServiceRecord record) {
-        return mServices.remove(record);
+        final boolean removed = mServices.remove(record);
+        if (record.lastTopAlmostPerceptibleBindRequestUptimeMs > 0) {
+            updateHasTopStartedAlmostPerceptibleServices();
+        }
+        return removed;
     }
 
     /**
@@ -261,6 +326,7 @@
      */
     void stopAllServices() {
         mServices.clear();
+        updateHasTopStartedAlmostPerceptibleServices();
     }
 
     /**
@@ -408,6 +474,13 @@
             pw.print(prefix); pw.print("mHasForegroundServices="); pw.print(mHasForegroundServices);
             pw.print(" forcingToImportant="); pw.println(mApp.mState.getForcingToImportant());
         }
+        if (mHasTopStartedAlmostPerceptibleServices
+                || mLastTopStartedAlmostPerceptibleBindRequestUptimeMs > 0) {
+            pw.print(prefix); pw.print("mHasTopStartedAlmostPerceptibleServices=");
+            pw.print(mHasTopStartedAlmostPerceptibleServices);
+            pw.print(" mLastTopStartedAlmostPerceptibleBindRequestUptimeMs=");
+            pw.println(mLastTopStartedAlmostPerceptibleBindRequestUptimeMs);
+        }
         if (mHasClientActivities || mHasAboveClient || mTreatLikeActivity) {
             pw.print(prefix); pw.print("hasClientActivities="); pw.print(mHasClientActivities);
             pw.print(" hasAboveClient="); pw.print(mHasAboveClient);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 795311f..639f56c 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -24,6 +24,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.IApplicationThread;
 import android.app.Notification;
@@ -141,6 +142,12 @@
     int pendingConnectionGroup;        // To be filled in to ProcessRecord once it connects
     int pendingConnectionImportance;   // To be filled in to ProcessRecord once it connects
 
+    /**
+     * The last time (in uptime timebase) a bind request was made with BIND_ALMOST_PERCEPTIBLE for
+     * this service while on TOP.
+     */
+    long lastTopAlmostPerceptibleBindRequestUptimeMs;
+
     // any current binding to this service has BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS flag?
     private boolean mIsAllowedBgActivityStartsByBinding;
     // is this service currently allowed to start activities from background by providing
@@ -713,6 +720,7 @@
         }
     }
 
+    @NonNull
     ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
         return connections;
     }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 0e29041..69b75e6 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1154,6 +1154,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/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
index 0f0032b..1d90954 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -198,7 +198,7 @@
 
     protected final void vibrateSuccess() {
         Vibrator vibrator = getContext().getSystemService(Vibrator.class);
-        if (vibrator != null) {
+        if (vibrator != null && mShouldVibrate) {
             vibrator.vibrate(Process.myUid(),
                     getContext().getOpPackageName(),
                     SUCCESS_VIBRATION_EFFECT,
@@ -209,7 +209,7 @@
 
     protected final void vibrateError() {
         Vibrator vibrator = getContext().getSystemService(Vibrator.class);
-        if (vibrator != null) {
+        if (vibrator != null && mShouldVibrate) {
             vibrator.vibrate(Process.myUid(),
                     getContext().getOpPackageName(),
                     ERROR_VIBRATION_EFFECT,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index bb1fed0..f23659c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -34,6 +34,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.accessibility.AccessibilityManager;
 
 import com.android.server.biometrics.HardwareAuthTokenUtils;
 import com.android.server.biometrics.log.BiometricContext;
@@ -66,6 +67,13 @@
     private final int mMaxTemplatesPerUser;
     private boolean mIsPointerDown;
 
+    private static boolean shouldVibrateFor(Context context,
+            FingerprintSensorPropertiesInternal sensorProps) {
+        final AccessibilityManager am = context.getSystemService(AccessibilityManager.class);
+        final boolean isAccessbilityEnabled = am.isTouchExplorationEnabled();
+        return !sensorProps.isAnyUdfpsType() || isAccessbilityEnabled;
+    }
+
     FingerprintEnrollClient(@NonNull Context context,
             @NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token, long requestId,
             @NonNull ClientMonitorCallbackConverter listener, int userId,
@@ -78,8 +86,8 @@
             int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) {
         // UDFPS haptics occur when an image is acquired (instead of when the result is known)
         super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
-                0 /* timeoutSec */, sensorId,
-                !sensorProps.isAnyUdfpsType() /* shouldVibrate */, logger, biometricContext);
+                0 /* timeoutSec */, sensorId, shouldVibrateFor(context, sensorProps), logger,
+                biometricContext);
         setRequestId(requestId);
         mSensorProps = sensorProps;
         mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
@@ -119,7 +127,7 @@
         // For UDFPS, notify SysUI that the illumination can be turned off.
         // See AcquiredInfo#GOOD and AcquiredInfo#RETRYING_CAPTURE
         if (mSensorProps.isAnyUdfpsType()) {
-            if (acquiredGood) {
+            if (acquiredGood && mShouldVibrate) {
                 vibrateSuccess();
             }
             mSensorOverlays.ifUdfps(
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 064e307..d12c621 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -30,9 +30,8 @@
 import android.util.Spline;
 import android.view.DisplayAddress;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.server.display.config.BrightnessThresholds;
 import com.android.server.display.config.BrightnessThrottlingMap;
@@ -296,9 +295,9 @@
      * @return A configuration instance for the specified display.
      */
     public static DisplayDeviceConfig create(Context context, long physicalDisplayId,
-            boolean isDefaultDisplay) {
+            boolean isFirstDisplay) {
         final DisplayDeviceConfig config = createWithoutDefaultValues(context, physicalDisplayId,
-                isDefaultDisplay);
+                isFirstDisplay);
 
         config.copyUninitializedValuesFromSecondaryConfig(loadDefaultConfigurationXml(context));
         return config;
@@ -323,7 +322,7 @@
     }
 
     private static DisplayDeviceConfig createWithoutDefaultValues(Context context,
-            long physicalDisplayId, boolean isDefaultDisplay) {
+            long physicalDisplayId, boolean isFirstDisplay) {
         DisplayDeviceConfig config;
 
         config = loadConfigFromDirectory(context, Environment.getProductDirectory(),
@@ -341,7 +340,7 @@
         // If no config can be loaded from any ddc xml at all,
         // prepare a whole config using the global config.xml.
         // Guaranteed not null
-        return create(context, isDefaultDisplay);
+        return create(context, isFirstDisplay);
     }
 
     private static DisplayConfiguration loadDefaultConfigurationXml(Context context) {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index a311ba1..edaa18a 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -39,7 +39,7 @@
      * Flag: Indicates that this display device should be considered the default display
      * device of the system.
      */
-    public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
+    public static final int FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY = 1 << 0;
 
     /**
      * Flag: Indicates that the orientation of this display device is coupled to the
@@ -538,8 +538,8 @@
 
     private static String flagsToString(int flags) {
         StringBuilder msg = new StringBuilder();
-        if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
-            msg.append(", FLAG_DEFAULT_DISPLAY");
+        if ((flags & FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0) {
+            msg.append(", FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY");
         }
         if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
             msg.append(", FLAG_ROTATES_WITH_CONTENT");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e4c12e6..932717a 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -397,8 +397,7 @@
     private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>();
 
     // The default color mode for default displays. Overrides the usual
-    // Display.Display.COLOR_MODE_DEFAULT for displays with the
-    // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
+    // Display.Display.COLOR_MODE_DEFAULT for local displays.
     private final int mDefaultDisplayDefaultColorMode;
 
     // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
@@ -1682,8 +1681,7 @@
         if (display.getPrimaryDisplayDeviceLocked() == device) {
             int colorMode = mPersistentDataStore.getColorMode(device);
             if (colorMode == Display.COLOR_MODE_INVALID) {
-                if ((device.getDisplayDeviceInfoLocked().flags
-                     & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
+                if (display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) {
                     colorMode = mDefaultDisplayDefaultColorMode;
                 } else {
                     colorMode = Display.COLOR_MODE_DEFAULT;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 540ae81..eaa1d4b 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -141,9 +141,9 @@
             LocalDisplayDevice device = mDevices.get(physicalDisplayId);
             if (device == null) {
                 // Display was added.
-                final boolean isDefaultDisplay = mDevices.size() == 0;
+                final boolean isFirstDisplay = mDevices.size() == 0;
                 device = new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,
-                        dynamicInfo, modeSpecs, isDefaultDisplay);
+                        dynamicInfo, modeSpecs, isFirstDisplay);
                 mDevices.put(physicalDisplayId, device);
                 sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
             } else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,
@@ -187,7 +187,7 @@
         private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
         private final DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
                 new DisplayModeDirector.DesiredDisplayModeSpecs();
-        private final boolean mIsDefaultDisplay;
+        private final boolean mIsFirstDisplay;
         private final BacklightAdapter mBacklightAdapter;
         private final SidekickInternal mSidekickInternal;
 
@@ -226,14 +226,14 @@
         LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
                 SurfaceControl.StaticDisplayInfo staticDisplayInfo,
                 SurfaceControl.DynamicDisplayInfo dynamicInfo,
-                SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isDefaultDisplay) {
+                SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isFirstDisplay) {
             super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId,
                     getContext());
             mPhysicalDisplayId = physicalDisplayId;
-            mIsDefaultDisplay = isDefaultDisplay;
+            mIsFirstDisplay = isFirstDisplay;
             updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
             mSidekickInternal = LocalServices.getService(SidekickInternal.class);
-            mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay,
+            mBacklightAdapter = new BacklightAdapter(displayToken, isFirstDisplay,
                     mSurfaceControlProxy);
             mActiveDisplayModeAtStartId = dynamicInfo.activeDisplayModeId;
         }
@@ -480,7 +480,7 @@
             // Load display device config
             final Context context = getOverlayContext();
             mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId,
-                    mIsDefaultDisplay);
+                    mIsFirstDisplay);
 
             // Load brightness HWC quirk
             mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
@@ -652,9 +652,9 @@
 
                 final Resources res = getOverlayContext().getResources();
 
-                if (mIsDefaultDisplay) {
-                    mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY;
+                mInfo.flags |= DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
 
+                if (mIsFirstDisplay) {
                     if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
                             || (Build.IS_EMULATOR
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
@@ -1438,9 +1438,9 @@
 
         /**
          * @param displayToken Token for display associated with this backlight.
-         * @param isDefaultDisplay {@code true} if it is the default display.
+         * @param isFirstDisplay {@code true} if it is the first display.
          */
-        BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay,
+        BacklightAdapter(IBinder displayToken, boolean isFirstDisplay,
                 SurfaceControlProxy surfaceControlProxy) {
             mDisplayToken = displayToken;
             mSurfaceControlProxy = surfaceControlProxy;
@@ -1448,7 +1448,7 @@
             mUseSurfaceControlBrightness = mSurfaceControlProxy
                     .getDisplayBrightnessSupport(mDisplayToken);
 
-            if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
+            if (!mUseSurfaceControlBrightness && isFirstDisplay) {
                 LightsManager lights = LocalServices.getService(LightsManager.class);
                 mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
             } else {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index add0a9f..70c9e23 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -16,6 +16,8 @@
 
 package com.android.server.display;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.devicestate.DeviceStateManager;
@@ -204,6 +206,7 @@
                 if (DEBUG) {
                     Slog.d(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
                 }
+                handleDisplayDeviceRemovedLocked(device);
                 updateLogicalDisplaysLocked();
                 break;
         }
@@ -529,12 +532,12 @@
 
     private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
-        // Internal Displays need to have additional initialization.
-        // This initializes a default dynamic display layout for INTERNAL
-        // devices, which is used as a fallback in case no static layout definitions
+        // The default Display needs to have additional initialization.
+        // This initializes a default dynamic display layout for the default
+        // device, which is used as a fallback in case no static layout definitions
         // exist or cannot be loaded.
-        if (deviceInfo.type == Display.TYPE_INTERNAL) {
-            initializeInternalDisplayDeviceLocked(device);
+        if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0) {
+            initializeDefaultDisplayDeviceLocked(device);
         }
 
         // Create a logical display for the new display device
@@ -545,6 +548,38 @@
         updateLogicalDisplaysLocked();
     }
 
+    private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
+        final Layout layout = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT);
+        Layout.Display layoutDisplay = layout.getById(DEFAULT_DISPLAY);
+        if (layoutDisplay == null) {
+            return;
+        }
+        DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
+
+        if (layoutDisplay.getAddress().equals(deviceInfo.address)) {
+            layout.removeDisplayLocked(DEFAULT_DISPLAY);
+
+            // Need to find another local display and make it default
+            for (int i = 0; i < mLogicalDisplays.size(); i++) {
+                LogicalDisplay nextDisplay = mLogicalDisplays.valueAt(i);
+                DisplayDevice nextDevice = nextDisplay.getPrimaryDisplayDeviceLocked();
+                if (nextDevice == null) {
+                    continue;
+                }
+                DisplayDeviceInfo nextDeviceInfo = nextDevice.getDisplayDeviceInfoLocked();
+
+                if ((nextDeviceInfo.flags
+                        & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0
+                        && !nextDeviceInfo.address.equals(deviceInfo.address)) {
+                    layout.createDisplayLocked(nextDeviceInfo.address,
+                            /* isDefault= */ true, /* isEnabled= */ true);
+                    applyLayoutLocked();
+                    return;
+                }
+            }
+        }
+    }
+
     /**
      * Updates the rest of the display system once all the changes are applied for display
      * devices and logical displays. The includes releasing invalid/empty LogicalDisplays,
@@ -900,16 +935,18 @@
         return isOwnDisplayGroup ? mNextNonDefaultGroupId++ : Display.DEFAULT_DISPLAY_GROUP;
     }
 
-    private void initializeInternalDisplayDeviceLocked(DisplayDevice device) {
+    private void initializeDefaultDisplayDeviceLocked(DisplayDevice device) {
         // We always want to make sure that our default layout creates a logical
-        // display for every internal display device that is found.
-        // To that end, when we are notified of a new internal display, we add it to
+        // display for the default display device that is found.
+        // To that end, when we are notified of a new default display, we add it to
         // the default layout definition if it is not already there.
         final Layout layout = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT);
+        if (layout.getById(DEFAULT_DISPLAY) != null) {
+            // The layout should only have one default display
+            return;
+        }
         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
-        final boolean isDefault = (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
-        final boolean isEnabled = isDefault || mSupportsConcurrentInternalDisplays;
-        layout.createDisplayLocked(info.address, isDefault, isEnabled);
+        layout.createDisplayLocked(info.address, /* isDefault= */ true, /* isEnabled= */ true);
     }
 
     private int assignLayerStackLocked(int displayId) {
diff --git a/services/core/java/com/android/server/display/layout/Layout.java b/services/core/java/com/android/server/display/layout/Layout.java
index e53aec1..7e16ea8 100644
--- a/services/core/java/com/android/server/display/layout/Layout.java
+++ b/services/core/java/com/android/server/display/layout/Layout.java
@@ -67,7 +67,7 @@
         // See if we're dealing with the "default" display
         if (isDefault && getById(DEFAULT_DISPLAY) != null) {
             Slog.w(TAG, "Ignoring attempt to add a second default display: " + address);
-            isDefault = false;
+            return null;
         }
 
         // Assign a logical display ID and create the new display.
@@ -75,10 +75,20 @@
         // different layouts, a logical display can be destroyed and later recreated with the
         // same logical display ID.
         final int logicalDisplayId = assignDisplayIdLocked(isDefault);
-        final Display layout = new Display(address, logicalDisplayId, isEnabled);
+        final Display display = new Display(address, logicalDisplayId, isEnabled);
 
-        mDisplays.add(layout);
-        return layout;
+        mDisplays.add(display);
+        return display;
+    }
+
+    /**
+     * @param id The ID of the display to remove.
+     */
+    public void removeDisplayLocked(int id) {
+        Display display = getById(id);
+        if (display != null) {
+            mDisplays.remove(display);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 0e1c1ad..dc4dd12 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -43,6 +43,7 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.SharedLibraryInfo;
+import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
 import android.net.Uri;
 import android.os.Binder;
@@ -161,6 +162,15 @@
                 return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
             }
 
+            if (PackageManagerServiceUtils.isSystemApp(uninstalledPs)) {
+                UserInfo userInfo = mUserManagerInternal.getUserInfo(userId);
+                if (userInfo == null || !userInfo.isAdmin()) {
+                    Slog.w(TAG, "Not removing package " + packageName
+                            + " as only admin user may downgrade system apps");
+                    return PackageManager.DELETE_FAILED_USER_RESTRICTED;
+                }
+            }
+
             disabledSystemPs = mPm.mSettings.getDisabledSystemPkgLPr(packageName);
             // Static shared libs can be declared by any package, so let us not
             // allow removing a package if it provides a lib others depend on.
diff --git a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
index 0ee07b6..5597c9a 100644
--- a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
+++ b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
@@ -21,14 +21,11 @@
 import android.Manifest;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
-import android.os.RemoteException;
 import android.provider.DeviceConfig;
-import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -39,10 +36,8 @@
 
 /**
  * Service to register an {@code ActivityInterceptorCallback} that modifies any {@code Intent}
- * that's being used to launch a user-space {@code ChooserActivity}, by adding
- * EXTRA_PERMISSION_TOKEN, a Binder representing a single-use-only permission to invoke the
- * #startActivityAsCaller() API (which normally isn't available in user-space); and setting the
- * destination component to the delegated component when appropriate.
+ * that's being used to launch a user-space {@code ChooserActivity} by setting the destination
+ * component to the delegated component when appropriate.
  */
 public final class IntentResolverInterceptor {
     private static final String TAG = "IntentResolverIntercept";
@@ -92,7 +87,6 @@
 
     private Intent modifyChooserIntent(Intent intent) {
         intent.setComponent(getUnbundledChooserComponentName());
-        addStartActivityPermissionTokenToIntent(intent, getUnbundledChooserComponentName());
         return intent;
     }
 
@@ -103,18 +97,6 @@
                 || targetComponent.equals(getUnbundledChooserComponentName());
     }
 
-    private static Intent addStartActivityPermissionTokenToIntent(
-            Intent intent, ComponentName grantee) {
-        try {
-            intent.putExtra(
-                    ActivityTaskManager.EXTRA_PERMISSION_TOKEN,
-                    ActivityTaskManager.getService().requestStartActivityPermissionToken(grantee));
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Failed to add permission token to chooser intent");
-        }
-        return intent;
-    }
-
     private static ComponentName getSystemChooserComponentName() {
         return new ComponentName("android", "com.android.internal.app.ChooserActivity");
     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5ba4cc1..1efaa73 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -272,7 +272,7 @@
 
     /**
      * The default value of {@link #mValidatedTargetSdk} is {@link Integer#MAX_VALUE}. If {@link
-     * #mValidatedTargetSdk} is compared with {@link Build.VERSION_CODES#Q} before getting the
+     * #mValidatedTargetSdk} is compared with {@link Build.VERSION_CODES#R} before getting the
      * target sdk version from a validated apk in {@link #validateApkInstallLocked()}, the compared
      * result will not trigger any user action in
      * {@link #checkUserActionRequirement(PackageInstallerSession)}.
@@ -2083,7 +2083,7 @@
             }
 
             if (validatedTargetSdk != INVALID_TARGET_SDK_VERSION
-                    && validatedTargetSdk < Build.VERSION_CODES.Q) {
+                    && validatedTargetSdk < Build.VERSION_CODES.R) {
                 session.sendPendingUserActionIntent(target);
                 return true;
             }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index b2b59f1..9ce4cdf 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -338,7 +338,7 @@
 
     public void ensureAllShortcutsVisibleToLauncher(@NonNull List<ShortcutInfo> shortcuts) {
         for (ShortcutInfo shortcut : shortcuts) {
-            if (!shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) {
+            if (shortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER)) {
                 throw new IllegalArgumentException("Shortcut ID=" + shortcut.getId()
                         + " is hidden from launcher and may not be manipulated via APIs");
             }
@@ -399,7 +399,7 @@
                     & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL));
         }
 
-        if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) {
+        if (newShortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER)) {
             if (isAppSearchEnabled()) {
                 synchronized (mLock) {
                     mTransientShortcuts.put(newShortcut.getId(), newShortcut);
@@ -477,7 +477,7 @@
                     & (ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_CACHED_ALL));
         }
 
-        if (!newShortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER)) {
+        if (newShortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER)) {
             if (isAppSearchEnabled()) {
                 synchronized (mLock) {
                     mTransientShortcuts.put(newShortcut.getId(), newShortcut);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 25fe000..9ca4f24 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2228,7 +2228,7 @@
         Objects.requireNonNull(shortcut);
         Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
         Preconditions.checkArgument(
-                shortcut.isIncludedIn(ShortcutInfo.SURFACE_LAUNCHER),
+                !shortcut.isExcludedFromSurfaces(ShortcutInfo.SURFACE_LAUNCHER),
                 "Shortcut excluded from launcher cannot be pinned");
         ret.complete(String.valueOf(requestPinItem(
                 packageName, userId, shortcut, null, null, resultIntent)));
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5aa81ac..999428a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1491,11 +1491,19 @@
     }
 
     private long getAccessibilityShortcutTimeout() {
-        ViewConfiguration config = ViewConfiguration.get(mContext);
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, mCurrentUserId) == 0
-                ? config.getAccessibilityShortcutKeyTimeout()
-                : config.getAccessibilityShortcutKeyTimeoutAfterConfirmation();
+        final ViewConfiguration config = ViewConfiguration.get(mContext);
+        final boolean hasDialogShown = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, mCurrentUserId) != 0;
+        final boolean skipTimeoutRestriction =
+                Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.SKIP_ACCESSIBILITY_SHORTCUT_DIALOG_TIMEOUT_RESTRICTION, 0,
+                        mCurrentUserId) != 0;
+
+        // If users manually set the volume key shortcut for any accessibility service, the
+        // system would bypass the timeout restriction of the shortcut dialog.
+        return hasDialogShown || skipTimeoutRestriction
+                ? config.getAccessibilityShortcutKeyTimeoutAfterConfirmation()
+                : config.getAccessibilityShortcutKeyTimeout();
     }
 
     private long getScreenshotChordLongPressDelay() {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index a486364..8f4ddea 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.trust;
 
+import static android.service.trust.GrantTrustResult.STATUS_UNLOCKED_BY_GRANT;
 import static android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE;
 
 import android.Manifest;
@@ -642,9 +643,7 @@
         if (shouldSendCallback) {
             if (resultCallback != null) {
                 if (DEBUG) Slog.d(TAG, "calling back with UNLOCKED_BY_GRANT");
-                resultCallback.complete(
-                        GrantTrustResult.withStatus(
-                                GrantTrustResult.STATUS_UNLOCKED_BY_GRANT));
+                resultCallback.complete(new GrantTrustResult(STATUS_UNLOCKED_BY_GRANT));
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ad6f354..eacf205 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -421,30 +421,6 @@
     // How long to wait in getAutofillAssistStructure() for the activity to respond with the result.
     private static final int PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
 
-    // Permission tokens are used to temporarily granted a trusted app the ability to call
-    // #startActivityAsCaller.  A client is expected to dump its token after this time has elapsed,
-    // showing any appropriate error messages to the user.
-    private static final long START_AS_CALLER_TOKEN_TIMEOUT =
-            10 * MINUTE_IN_MILLIS;
-
-    // How long before the service actually expires a token.  This is slightly longer than
-    // START_AS_CALLER_TOKEN_TIMEOUT, to provide a buffer so clients will rarely encounter the
-    // expiration exception.
-    private static final long START_AS_CALLER_TOKEN_TIMEOUT_IMPL =
-            START_AS_CALLER_TOKEN_TIMEOUT + 2 * 1000;
-
-    // How long the service will remember expired tokens, for the purpose of providing error
-    // messaging when a client uses an expired token.
-    private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT =
-            START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS;
-
-    // The component name of the delegated activities that are allowed to call
-    // #startActivityAsCaller with the one-time used permission token.
-    final HashMap<IBinder, ComponentName> mStartActivitySources = new HashMap<>();
-
-    // Permission tokens that have expired, but we remember for error reporting.
-    final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>();
-
     private final ArrayList<PendingAssistExtras> mPendingAssistExtras = new ArrayList<>();
 
     // Keeps track of the active voice interaction service component, notified from
@@ -1547,41 +1523,19 @@
     }
 
     @Override
-    public IBinder requestStartActivityPermissionToken(ComponentName componentName) {
-        int callingUid = Binder.getCallingUid();
-        if (UserHandle.getAppId(callingUid) != SYSTEM_UID) {
-            throw new SecurityException("Only the system process can request a permission token, "
-                    + "received request from uid: " + callingUid);
-        }
-        IBinder permissionToken = new Binder();
-        synchronized (mGlobalLock) {
-            mStartActivitySources.put(permissionToken, componentName);
-        }
-
-        Message expireMsg = PooledLambda.obtainMessage(
-                ActivityTaskManagerService::expireStartAsCallerTokenMsg, this, permissionToken);
-        mUiHandler.sendMessageDelayed(expireMsg, START_AS_CALLER_TOKEN_TIMEOUT_IMPL);
-
-        Message forgetMsg = PooledLambda.obtainMessage(
-                ActivityTaskManagerService::forgetStartAsCallerTokenMsg, this, permissionToken);
-        mUiHandler.sendMessageDelayed(forgetMsg, START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT);
-
-        return permissionToken;
-    }
-
-    @Override
     public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, IBinder permissionToken,
+            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions,
             boolean ignoreTargetSecurity, int userId) {
         // This is very dangerous -- it allows you to perform a start activity (including
         // permission grants) as any app that may launch one of your own activities.  So we only
         // allow this in two cases:
-        // 1)  The caller is an activity that is part of the core framework, and then only when it
-        //     is running as the system.
-        // 2)  The caller provides a valid permissionToken.  Permission tokens are one-time use and
-        //     can only be requested from system uid, which may then delegate this call to
-        //     another app.
+        // 1)  The calling process holds the signature permission START_ACTIVITY_AS_CALLER
+        //
+        // 2) The calling process is an activity belonging to the package "android" which is
+        //    running as UID_SYSTEM or as the target UID (the activity which started the activity
+        //    calling this method).
+
         final ActivityRecord sourceRecord;
         final int targetUid;
         final String targetPackage;
@@ -1600,26 +1554,8 @@
                 throw new SecurityException("Called without a process attached to activity");
             }
 
-            final ComponentName componentName;
-            if (permissionToken != null) {
-                // To even attempt to use a permissionToken, an app must also have this signature
-                // permission.
-                mAmInternal.enforceCallingPermission(
-                        android.Manifest.permission.START_ACTIVITY_AS_CALLER,
-                        "startActivityAsCaller");
-                // If called with a permissionToken, the caller must be the same component that
-                // was allowed to use the permissionToken.
-                componentName = mStartActivitySources.remove(permissionToken);
-                if (!sourceRecord.mActivityComponent.equals(componentName)) {
-                    if (mExpiredStartAsCallerTokens.contains(permissionToken)) {
-                        throw new SecurityException("Called with expired permission token: "
-                                + permissionToken);
-                    } else {
-                        throw new SecurityException("Called with invalid permission token: "
-                                + permissionToken);
-                    }
-                }
-            } else {
+            if (checkCallingPermission(Manifest.permission.START_ACTIVITY_AS_CALLER)
+                    != PERMISSION_GRANTED) {
                 // Whether called directly or from a delegate, the source activity must be from the
                 // android package.
                 if (!sourceRecord.info.packageName.equals("android")) {
@@ -4453,15 +4389,6 @@
         Settings.System.putConfigurationForUser(resolver, config, userId);
     }
 
-    private void expireStartAsCallerTokenMsg(IBinder permissionToken) {
-        mStartActivitySources.remove(permissionToken);
-        mExpiredStartAsCallerTokens.add(permissionToken);
-    }
-
-    private void forgetStartAsCallerTokenMsg(IBinder permissionToken) {
-        mExpiredStartAsCallerTokens.remove(permissionToken);
-    }
-
     boolean isActivityStartsLoggingEnabled() {
         return mAmInternal.isActivityStartsLoggingEnabled();
     }
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 3a8c8c7..18a7640 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -251,7 +251,13 @@
             // possible.
             while (!mOrganizedTasks.isEmpty()) {
                 final Task t = mOrganizedTasks.get(0);
-                t.updateTaskOrganizerState(true /* forceUpdate */);
+                if (t.mCreatedByOrganizer) {
+                    // The tasks created by this organizer should ideally be deleted when this
+                    // organizer is disposed off to avoid inconsistent behavior.
+                    t.removeImmediately();
+                } else {
+                    t.updateTaskOrganizerState(true /* forceUpdate */);
+                }
                 if (mOrganizedTasks.contains(t)) {
                     // updateTaskOrganizerState should remove the task from the list, but still
                     // check it again to avoid while-loop isn't terminate.
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 486b6a1..b0fe397 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -13986,16 +13986,10 @@
                         return;
                     }
                 }
-                try {
-                    if (!isRuntimePermission(permission)) {
-                        callback.sendResult(null);
-                        return;
-                    }
-                } catch (NameNotFoundException e) {
-                    throw new RemoteException("Cannot check if " + permission
-                            + "is a runtime permission", e, false, true);
+                if (!isRuntimePermission(permission)) {
+                    callback.sendResult(null);
+                    return;
                 }
-
                 if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
                         || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
                         || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
@@ -14108,11 +14102,15 @@
         });
     }
 
-    public boolean isRuntimePermission(String permissionName) throws NameNotFoundException {
-        final PackageManager packageManager = mInjector.getPackageManager();
-        PermissionInfo permissionInfo = packageManager.getPermissionInfo(permissionName, 0);
-        return (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
-                == PermissionInfo.PROTECTION_DANGEROUS;
+    private boolean isRuntimePermission(String permissionName) {
+        try {
+            final PackageManager packageManager = mInjector.getPackageManager();
+            PermissionInfo permissionInfo = packageManager.getPermissionInfo(permissionName, 0);
+            return (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                    == PermissionInfo.PROTECTION_DANGEROUS;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
     }
 
     @Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index e096687..4a51e41 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -217,6 +217,8 @@
     @Mock
     private AppOpsManager mAppOpsManager;
     @Mock
+    private BatteryManager mBatteryManager;
+    @Mock
     private DeviceIdleInternal mDeviceIdleInternal;
     @Mock
     private PermissionManagerServiceInternal mPermissionManagerInternal;
@@ -453,6 +455,7 @@
                         eq(Manifest.permission.USE_EXACT_ALARM), anyInt(), anyInt(), anyString()));
 
         when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+        when(mMockContext.getSystemService(BatteryManager.class)).thenReturn(mBatteryManager);
 
         registerAppIds(new String[]{TEST_CALLING_PACKAGE},
                 new Integer[]{UserHandle.getAppId(TEST_CALLING_UID)});
@@ -477,6 +480,8 @@
 
         // Other boot phases don't matter
         mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
+
+        verify(mBatteryManager).isCharging();
         setTareEnabled(false);
         mAppStandbyWindow = mService.mConstants.APP_STANDBY_WINDOW;
         mAllowWhileIdleWindow = mService.mConstants.ALLOW_WHILE_IDLE_WINDOW;
@@ -1101,6 +1106,7 @@
                 new Intent(parole ? BatteryManager.ACTION_CHARGING
                         : BatteryManager.ACTION_DISCHARGING));
         assertAndHandleMessageSync(CHARGING_STATUS_CHANGED);
+        assertEquals(parole, mService.mAppStandbyParole);
     }
 
     @Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 50a0a68..c747a5f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -63,6 +63,7 @@
 import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalAnswers.answer;
 import static org.mockito.Mockito.any;
@@ -444,7 +445,7 @@
 
     @SuppressWarnings("GuardedBy")
     @Test
-    public void testUpdateOomAdj_DoOne_PerceptibleRecent() {
+    public void testUpdateOomAdj_DoOne_PerceptibleRecent_FgService() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
         app.mServices.setHasForegroundServices(true, 0);
@@ -458,6 +459,70 @@
 
     @SuppressWarnings("GuardedBy")
     @Test
+    public void testUpdateOomAdj_DoOne_PerceptibleRecent_AlmostPerceptibleService() {
+        // Grace period allows the adjustment.
+        {
+            ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+            long nowUptime = SystemClock.uptimeMillis();
+            app.mState.setLastTopTime(nowUptime);
+            // Simulate the system starting and binding to a service in the app.
+            ServiceRecord s = bindService(app, system,
+                    null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            s.lastTopAlmostPerceptibleBindRequestUptimeMs = nowUptime;
+            s.getConnections().clear();
+            app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+        }
+
+        // Out of grace period but valid binding allows the adjustment.
+        {
+            ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+            long nowUptime = SystemClock.uptimeMillis();
+            app.mState.setLastTopTime(nowUptime);
+            // Simulate the system starting and binding to a service in the app.
+            ServiceRecord s = bindService(app, system,
+                    null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            s.lastTopAlmostPerceptibleBindRequestUptimeMs =
+                    nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
+            app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+        }
+
+        // Out of grace period and no valid binding so no adjustment.
+        {
+            ProcessRecord system = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                    MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
+            ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                    MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, true));
+            long nowUptime = SystemClock.uptimeMillis();
+            app.mState.setLastTopTime(nowUptime);
+            // Simulate the system starting and binding to a service in the app.
+            ServiceRecord s = bindService(app, system,
+                    null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+            s.lastTopAlmostPerceptibleBindRequestUptimeMs =
+                    nowUptime - 2 * sService.mConstants.mServiceBindAlmostPerceptibleTimeoutMs;
+            s.getConnections().clear();
+            app.mServices.updateHasTopStartedAlmostPerceptibleServices();
+            sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+            sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+            assertNotEquals(PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ, app.mState.getSetAdj());
+        }
+    }
+    @SuppressWarnings("GuardedBy")
+    @Test
     public void testUpdateOomAdj_DoOne_Toast() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 8d6269c..617321b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -178,7 +178,7 @@
         // This should be public
         assertDisplayPrivateFlag(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(),
                 PORT_A, false);
-        // This should be public
+        // This should be private
         assertDisplayPrivateFlag(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(),
                 PORT_B, true);
         // This should be public
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
new file mode 100644
index 0000000..c9598bd
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/DeletePackageHelperTest.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.pm
+
+import android.content.pm.PackageManager
+import android.content.pm.UserInfo
+import android.os.Build
+import android.util.Log
+import com.android.server.testutils.any
+import com.android.server.testutils.spy
+import com.android.server.testutils.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.doAnswer
+
+@RunWith(JUnit4::class)
+class DeletePackageHelperTest {
+
+    @Rule
+    @JvmField
+    val rule = MockSystemRule()
+
+    private lateinit var mPms: PackageManagerService
+    private lateinit var mUserManagerInternal: UserManagerInternal
+
+    @Before
+    @Throws(Exception::class)
+    fun setup() {
+        Log.i("system.out", "setup", Exception())
+        rule.system().stageNominalSystemState()
+        rule.system().stageScanExistingPackage(
+            "a.data.package", 1L, rule.system().dataAppDirectory)
+
+        mUserManagerInternal = rule.mocks().injector.userManagerInternal
+        whenever(mUserManagerInternal.getUserIds()).thenReturn(intArrayOf(0, 1))
+
+        mPms = createPackageManagerService()
+        doAnswer { false }.`when`(mPms).isPackageDeviceAdmin(any(), any())
+        doAnswer { null }.`when`(mPms).freezePackageForDelete(any(), any(), any(), any())
+    }
+
+    private fun createPackageManagerService(): PackageManagerService {
+        return spy(PackageManagerService(rule.mocks().injector,
+            false /*coreOnly*/,
+            false /*factoryTest*/,
+            MockSystem.DEFAULT_VERSION_INFO.fingerprint,
+            false /*isEngBuild*/,
+            false /*isUserDebugBuild*/,
+            Build.VERSION_CODES.CUR_DEVELOPMENT,
+            Build.VERSION.INCREMENTAL))
+    }
+
+    @Test
+    fun deleteSystemPackageFailsIfNotAdmin() {
+        val ps = mPms.mSettings.getPackageLPr("a.data.package")
+        whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+        whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(UserInfo(1, "test", 0))
+
+        val dph = DeletePackageHelper(mPms)
+        val result = dph.deletePackageX("a.data.package", 1L, 1, 0, false)
+
+        assertThat(result).isEqualTo(PackageManager.DELETE_FAILED_USER_RESTRICTED)
+    }
+
+    @Test
+    fun deleteSystemPackageSucceedsIfAdmin() {
+        val ps = mPms.mSettings.getPackageLPr("a.data.package")
+        whenever(PackageManagerServiceUtils.isSystemApp(ps)).thenReturn(true)
+        whenever(mUserManagerInternal.getUserInfo(1)).thenReturn(
+            UserInfo(1, "test", UserInfo.FLAG_ADMIN))
+
+        val dph = DeletePackageHelper(mPms)
+        val result = dph.deletePackageX("a.data.package", 1L, 1,
+            PackageManager.DELETE_SYSTEM_APP, false)
+
+        assertThat(result).isEqualTo(PackageManager.DELETE_SUCCEEDED)
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index 27637c2..ed0336a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -21,6 +21,7 @@
 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
+import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
 import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
@@ -42,6 +43,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.provider.Settings;
@@ -92,6 +94,8 @@
 
     @Mock private AccessibilityUserState.ServiceInfoChangeListener mMockListener;
 
+    @Mock private PackageManager mMockPackageManager;
+
     @Mock private Context mMockContext;
 
     private MockContentResolver mMockResolver;
@@ -113,6 +117,8 @@
         when(mMockServiceInfo.getComponentName()).thenReturn(COMPONENT_NAME);
         when(mMockConnection.getServiceInfo()).thenReturn(mMockServiceInfo);
         when(mMockContext.getResources()).thenReturn(resources);
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockPackageManager.hasSystemFeature(FEATURE_WINDOW_MAGNIFICATION)).thenReturn(true);
 
         mFocusStrokeWidthDefaultValue =
                 resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width);
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index 1fb5898..bf3c7c3 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -393,7 +393,8 @@
         displayDeviceInfo.displayCutout = new DisplayCutout(
                 Insets.of(0, 10, 0, 0),
                 zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
-        displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY;
+        displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
+        displayDeviceInfo.address = new TestUtils.TestDisplayAddress();
         displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
         displayManager.getDisplayDeviceRepository()
                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
@@ -1307,7 +1308,8 @@
         displayDeviceInfo.displayCutout = new DisplayCutout(
                 Insets.of(0, 10, 0, 0),
                 zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
-        displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY;
+        displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
+        displayDeviceInfo.address = new TestUtils.TestDisplayAddress();
         displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
         displayManager.getDisplayDeviceRepository()
                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 86b6da0..cc68ba8 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -42,7 +42,6 @@
 import android.os.Handler;
 import android.os.IPowerManager;
 import android.os.IThermalService;
-import android.os.Parcel;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.test.TestLooper;
@@ -146,7 +145,7 @@
     @Test
     public void testDisplayDeviceAddAndRemove_Internal() {
         DisplayDevice device = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY);
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
 
         // add
         LogicalDisplay displayAdded = add(device);
@@ -179,7 +178,7 @@
     public void testDisplayDeviceAdd_TwoInternalOneDefault() {
         DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0);
         DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY);
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
 
         LogicalDisplay display1 = add(device1);
         assertEquals(info(display1).address, info(device1).address);
@@ -193,9 +192,9 @@
     @Test
     public void testDisplayDeviceAdd_TwoInternalBothDefault() {
         DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY);
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
         DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY);
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
 
         LogicalDisplay display1 = add(device1);
         assertEquals(info(display1).address, info(device1).address);
@@ -208,9 +207,57 @@
     }
 
     @Test
+    public void testDisplayDeviceAddAndRemove_OneExternalDefault() {
+        DisplayDevice device = createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800,
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+
+        // add
+        LogicalDisplay displayAdded = add(device);
+        assertEquals(info(displayAdded).address, info(device).address);
+        assertEquals(Display.DEFAULT_DISPLAY, id(displayAdded));
+
+        // remove
+        mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED);
+        verify(mListenerMock).onLogicalDisplayEventLocked(
+                mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
+        LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
+        assertEquals(DEFAULT_DISPLAY, id(displayRemoved));
+        assertEquals(displayAdded, displayRemoved);
+    }
+
+    @Test
+    public void testDisplayDeviceAddAndRemove_SwitchDefault() {
+        DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+        DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
+
+        LogicalDisplay display1 = add(device1);
+        assertEquals(info(display1).address, info(device1).address);
+        assertEquals(DEFAULT_DISPLAY, id(display1));
+
+        LogicalDisplay display2 = add(device2);
+        assertEquals(info(display2).address, info(device2).address);
+        // We can only have one default display
+        assertEquals(DEFAULT_DISPLAY, id(display1));
+
+        // remove
+        mDisplayDeviceRepo.onDisplayDeviceEvent(device1, DISPLAY_DEVICE_EVENT_REMOVED);
+
+        verify(mListenerMock).onLogicalDisplayEventLocked(
+                mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
+        LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
+        // Display 1 is still the default logical display
+        assertEquals(DEFAULT_DISPLAY, id(display1));
+        // The logical displays had their devices swapped and Display 2 was removed
+        assertEquals(display2, displayRemoved);
+        assertEquals(info(display1).address, info(device2).address);
+    }
+
+    @Test
     public void testGetDisplayIdsLocked() {
         add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800, 0));
         add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
 
@@ -223,19 +270,19 @@
     @Test
     public void testGetDisplayInfoForStateLocked_oneDisplayGroup_internalType() {
         add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_INTERNAL, 700, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
 
         Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked(
                 DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP);
-        assertThat(displayInfos.size()).isEqualTo(3);
+        assertThat(displayInfos.size()).isEqualTo(1);
         for (DisplayInfo displayInfo : displayInfos) {
             assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY);
             assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP);
-            assertThat(displayInfo.logicalWidth).isAnyOf(600, 200, 700);
+            assertThat(displayInfo.logicalWidth).isEqualTo(600);
             assertThat(displayInfo.logicalHeight).isEqualTo(800);
         }
     }
@@ -243,19 +290,19 @@
     @Test
     public void testGetDisplayInfoForStateLocked_oneDisplayGroup_differentTypes() {
         add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_EXTERNAL, 700, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
 
         Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked(
                 DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP);
-        assertThat(displayInfos.size()).isEqualTo(2);
+        assertThat(displayInfos.size()).isEqualTo(1);
         for (DisplayInfo displayInfo : displayInfos) {
             assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY);
             assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP);
-            assertThat(displayInfo.logicalWidth).isAnyOf(600, 200);
+            assertThat(displayInfo.logicalWidth).isEqualTo(600);
             assertThat(displayInfo.logicalHeight).isEqualTo(800);
         }
     }
@@ -263,19 +310,19 @@
     @Test
     public void testGetDisplayInfoForStateLocked_multipleDisplayGroups_defaultGroup() {
         add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         add(createDisplayDevice(Display.TYPE_VIRTUAL, 700, 800,
                 DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP));
 
         Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked(
                 DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP);
-        assertThat(displayInfos.size()).isEqualTo(2);
+        assertThat(displayInfos.size()).isEqualTo(1);
         for (DisplayInfo displayInfo : displayInfos) {
             assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY);
             assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP);
-            assertThat(displayInfo.logicalWidth).isAnyOf(600, 200);
+            assertThat(displayInfo.logicalWidth).isEqualTo(600);
             assertThat(displayInfo.logicalHeight).isEqualTo(800);
         }
     }
@@ -283,7 +330,7 @@
     @Test
     public void testSingleDisplayGroup() {
         LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0));
         LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0));
 
@@ -298,7 +345,7 @@
     @Test
     public void testMultipleDisplayGroups() {
         LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800,
-                DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY));
+                DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
         LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0));
 
 
@@ -371,7 +418,7 @@
     /////////////////
 
     private TestDisplayDevice createDisplayDevice(int type, int width, int height, int flags) {
-        return createDisplayDevice(new DisplayAddressImpl(), type, width, height, flags);
+        return createDisplayDevice(new TestUtils.TestDisplayAddress(), type, width, height, flags);
     }
 
     private TestDisplayDevice createDisplayDevice(
@@ -385,7 +432,7 @@
         displayDeviceInfo.supportedModes = new Display.Mode[1];
         displayDeviceInfo.supportedModes[0] = new Display.Mode(1, width, height, 60f);
         displayDeviceInfo.modeId = 1;
-        displayDeviceInfo.address = new DisplayAddressImpl();
+        displayDeviceInfo.address = address;
         return device;
     }
 
@@ -427,18 +474,8 @@
         assertNotEquals(DEFAULT_DISPLAY, id(displayRemoved));
     }
 
-    /**
-     * Create a custom {@link DisplayAddress} to ensure we're not relying on any specific
-     * display-address implementation in our code. Intentionally uses default object (reference)
-     * equality rules.
-     */
-    class DisplayAddressImpl extends DisplayAddress {
-        @Override
-        public void writeToParcel(Parcel out, int flags) { }
-    }
-
     class TestDisplayDevice extends DisplayDevice {
-        private DisplayDeviceInfo mInfo = new DisplayDeviceInfo();
+        private DisplayDeviceInfo mInfo;
         private DisplayDeviceInfo mSentInfo;
 
         TestDisplayDevice() {
diff --git a/services/tests/servicestests/src/com/android/server/display/TestUtils.java b/services/tests/servicestests/src/com/android/server/display/TestUtils.java
index 859dfe3..0454587 100644
--- a/services/tests/servicestests/src/com/android/server/display/TestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/display/TestUtils.java
@@ -18,7 +18,9 @@
 
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
+import android.os.Parcel;
 import android.os.SystemClock;
+import android.view.DisplayAddress;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
@@ -57,4 +59,13 @@
         return sensor;
     }
 
+    /**
+     * Create a custom {@link DisplayAddress} to ensure we're not relying on any specific
+     * display-address implementation in our code. Intentionally uses default object (reference)
+     * equality rules.
+     */
+    public static class TestDisplayAddress extends DisplayAddress {
+        @Override
+        public void writeToParcel(Parcel out, int flags) { }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 9faf499..eb91d5e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -309,6 +309,52 @@
     }
 
     @Test
+    public void testUnregisterOrganizer_removesTasksCreatedByIt() throws RemoteException {
+        final Task rootTask = createRootTask();
+        final Task task = createTask(rootTask);
+        final Task rootTask2 = createRootTask();
+        rootTask2.mCreatedByOrganizer = true;
+        final Task task2 = createTask(rootTask2);
+        final ArrayList<TaskAppearedInfo> existingTasks = new ArrayList<>();
+        final ITaskOrganizer organizer = registerMockOrganizer(existingTasks);
+        // Ensure events dispatch to organizer.
+        mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
+
+        // verify that tasks are returned and taskAppeared is called only for rootTask2 since it
+        // is the one created by this organizer.
+        assertContainsTasks(existingTasks, rootTask);
+        verify(organizer, times(1)).onTaskAppeared(any(RunningTaskInfo.class),
+                any(SurfaceControl.class));
+        verify(organizer, times(0)).onTaskVanished(any());
+        assertTrue(rootTask.isOrganized());
+
+        // Now we replace the registration and verify the new organizer receives existing tasks
+        final ArrayList<TaskAppearedInfo> existingTasks2 = new ArrayList<>();
+        final ITaskOrganizer organizer2 = registerMockOrganizer(existingTasks2);
+        // Ensure events dispatch to organizer.
+        mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
+        assertContainsTasks(existingTasks2, rootTask);
+        verify(organizer2, times(1)).onTaskAppeared(any(RunningTaskInfo.class),
+                any(SurfaceControl.class));
+        verify(organizer2, times(0)).onTaskVanished(any());
+        // Removed tasks from the original organizer
+        assertTaskVanished(organizer, true /* expectVanished */, rootTask, rootTask2);
+        assertTrue(rootTask2.isOrganized());
+
+        // Now we unregister the second one, the first one should automatically be reregistered
+        // so we verify that it's now seeing changes.
+        mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
+        // Ensure events dispatch to organizer.
+        mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents();
+
+        verify(organizer, times(2))
+                .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
+        assertFalse(rootTask2.isOrganized());
+        assertTaskVanished(organizer2, true /* expectVanished */, rootTask,
+                rootTask2);
+    }
+
+    @Test
     public void testOrganizerDeathReturnsRegistrationToPrevious() throws RemoteException {
         final Task rootTask = createRootTask();
         final Task task = createTask(rootTask);
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 0fa79df..04c52f7 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -84,7 +84,7 @@
     private final Object mLock = new Object();
     private boolean mIsOpen;
 
-    private final UsbMidiPacketConverter mUsbMidiPacketConverter = new UsbMidiPacketConverter();
+    private UsbMidiPacketConverter mUsbMidiPacketConverter;
 
     private final MidiDeviceServer.Callback mCallback = new MidiDeviceServer.Callback() {
 
@@ -264,6 +264,11 @@
         Log.d(TAG, "openLocked()");
         UsbManager manager = mContext.getSystemService(UsbManager.class);
 
+        // Converting from raw MIDI to USB MIDI is not thread-safe.
+        // UsbMidiPacketConverter creates a converter from raw MIDI
+        // to USB MIDI for each USB output.
+        mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
+
         mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>(mUsbInterfaces.size());
         mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
         mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>(mUsbInterfaces.size());
@@ -415,7 +420,7 @@
                             } else {
                                 convertedArray =
                                         mUsbMidiPacketConverter.rawMidiToUsbMidi(
-                                                 event.data, event.count);
+                                                 event.data, event.count, portFinal);
                             }
 
                             if (DEBUG) {
@@ -518,6 +523,8 @@
         mInputUsbEndpoints = null;
         mOutputUsbEndpoints = null;
 
+        mUsbMidiPacketConverter = null;
+
         mIsOpen = false;
     }
 
diff --git a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
index 7c93c76..56bb236 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
@@ -74,8 +74,15 @@
     private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
     private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
 
-    private UsbMidiEncoder mUsbMidiEncoder = new UsbMidiEncoder();
     private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
+    private UsbMidiEncoder[] mUsbMidiEncoders;
+
+    public UsbMidiPacketConverter(int numEncoders) {
+        mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
+        for (int i = 0; i < numEncoders; i++) {
+            mUsbMidiEncoders[i] = new UsbMidiEncoder();
+        }
+    }
 
     /**
      * Converts a USB MIDI array into a raw MIDI array.
@@ -93,10 +100,11 @@
      *
      * @param midiBytes the raw MIDI bytes to convert
      * @param size the size of usbMidiBytes
+     * @param encoderId which encoder to use
      * @return byte array of USB MIDI packets
      */
-    public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size) {
-        return mUsbMidiEncoder.encode(midiBytes, size);
+    public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
+        return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
     }
 
     private class UsbMidiDecoder {
diff --git a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationManagerService.java b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationManagerService.java
index 0d0b3e0..076059f 100644
--- a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationManagerService.java
+++ b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationManagerService.java
@@ -108,7 +108,7 @@
         @Override
         public void generateCinematicEffect(@NonNull CinematicEffectRequest request,
                 @NonNull ICinematicEffectListener listener) {
-            if (!runForUserLocked("generateCinematicEffect", (service) ->
+            if (!runForUser("generateCinematicEffect", true, (service) ->
                     service.onGenerateCinematicEffectLocked(request, listener))) {
                 try {
                     listener.onCinematicEffectGenerated(
@@ -126,7 +126,7 @@
 
         @Override
         public void returnCinematicEffectResponse(@NonNull CinematicEffectResponse response) {
-            runForUserLocked("returnCinematicResponse", (service) ->
+            runForUser("returnCinematicResponse", false, (service) ->
                     service.onReturnCinematicEffectResponseLocked(response));
         }
 
@@ -140,30 +140,42 @@
         }
 
         /**
-         * Execute the operation for the user locked. Return true if
-         * WallpaperEffectsGenerationPerUserService is found for the user.
-         * Otherwise return false.
+         * Execute the operation for the user.
+         *
+         * @param func The name of function for logging purpose.
+         * @param checkManageWallpaperEffectsPermission whether to check if caller has
+         *    MANAGE_WALLPAPER_EFFECTS_GENERATION.
+         *    If false, check the uid of caller matching bind service.
+         * @param c WallpaperEffectsGenerationPerUserService operation.
+         * @return whether WallpaperEffectsGenerationPerUserService is found.
          */
-        private boolean runForUserLocked(@NonNull final String func,
+        private boolean runForUser(@NonNull final String func,
+                @NonNull final boolean checkManageWallpaperEffectsPermission,
                 @NonNull final Consumer<WallpaperEffectsGenerationPerUserService> c) {
             ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
             final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                     Binder.getCallingUserHandle().getIdentifier(), false, ALLOW_NON_FULL,
                     null, null);
             if (DEBUG) {
-                Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid()
+                Slog.d(TAG, "runForUser:" + func + " from pid=" + Binder.getCallingPid()
                         + ", uid=" + Binder.getCallingUid());
             }
-            Context ctx = getContext();
-            if (!(ctx.checkCallingPermission(MANAGE_WALLPAPER_EFFECTS_GENERATION)
-                    == PERMISSION_GRANTED
-                    || mServiceNameResolver.isTemporary(userId)
-                    || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
-                String msg = "Permission Denial: Cannot call " + func + " from pid="
-                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
-                Slog.w(TAG, msg);
-                throw new SecurityException(msg);
+            if (checkManageWallpaperEffectsPermission) {
+                // MANAGE_WALLPAPER_EFFECTS_GENERATION is required for all functions except for
+                // "returnCinematicResponse", whose calling permission checked in
+                // WallpaperEffectsGenerationPerUserService against remote binding.
+                Context ctx = getContext();
+                if (!(ctx.checkCallingPermission(MANAGE_WALLPAPER_EFFECTS_GENERATION)
+                        == PERMISSION_GRANTED
+                        || mServiceNameResolver.isTemporary(userId)
+                        || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
+                    String msg = "Permission Denial: Cannot call " + func + " from pid="
+                            + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
+                    Slog.w(TAG, msg);
+                    throw new SecurityException(msg);
+                }
             }
+            final int origCallingUid = Binder.getCallingUid();
             final long origId = Binder.clearCallingIdentity();
             boolean accepted = false;
             try {
@@ -171,6 +183,16 @@
                     final WallpaperEffectsGenerationPerUserService service =
                             getServiceForUserLocked(userId);
                     if (service != null) {
+                        // Check uid of caller matches bind service implementation if
+                        // MANAGE_WALLPAPER_EFFECTS_GENERATION is skipped. This is useful
+                        // for service implementation to return response.
+                        if (!checkManageWallpaperEffectsPermission
+                                && !service.isCallingUidAllowed(origCallingUid)) {
+                            String msg = "Permission Denial: cannot call " + func + ", uid["
+                                    + origCallingUid + "] doesn't match service implementation";
+                            Slog.w(TAG, msg);
+                            throw new SecurityException(msg);
+                        }
                         accepted = true;
                         c.accept(service);
                     }
diff --git a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
index d541051..7ba72db 100644
--- a/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
+++ b/services/wallpapereffectsgeneration/java/com/android/server/wallpapereffectsgeneration/WallpaperEffectsGenerationPerUserService.java
@@ -141,6 +141,13 @@
         invokeCinematicListenerAndCleanup(cinematicEffectResponse);
     }
 
+    /**
+     * Checks whether the calling uid matches the bind service uid.
+     */
+    public boolean isCallingUidAllowed(int callingUid) {
+        return getServiceUidLocked() ==  callingUid;
+    }
+
     @GuardedBy("mLock")
     private void updateRemoteServiceLocked() {
         if (mRemoteService != null) {
@@ -152,7 +159,6 @@
             invokeCinematicListenerAndCleanup(
                     createErrorCinematicEffectResponse(mCinematicEffectListenerWrapper.mTaskId));
         }
-
     }
 
     void onPackageUpdatedLocked() {
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 98db291..78b0b84 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -68,7 +68,7 @@
 public final class SmsApplication {
     static final String LOG_TAG = "SmsApplication";
     public static final String PHONE_PACKAGE_NAME = "com.android.phone";
-    public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+    public static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth.services";
     public static final String MMS_SERVICE_PACKAGE_NAME = "com.android.mms.service";
     public static final String TELEPHONY_PROVIDER_PACKAGE_NAME = "com.android.providers.telephony";
 
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index 730a9d1..2d0135a 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -383,8 +383,6 @@
      * activity.
      */
     public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) {
-        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
-
         ActivityStatsTechSpecificInfo[] mDeltaSpecificInfo;
         mDeltaSpecificInfo = new ActivityStatsTechSpecificInfo[other.getSpecificInfoLength()];
 
@@ -399,6 +397,7 @@
                         if (other.mActivityStatsTechSpecificInfo[i].getFrequencyRange()
                                 == mActivityStatsTechSpecificInfo[j].getFrequencyRange()) {
                             int freq = mActivityStatsTechSpecificInfo[j].getFrequencyRange();
+                            int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
                             for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                                 txTimeMs[lvl] =
                                         (int) (other.getTransmitDurationMillisAtPowerLevel(
@@ -416,6 +415,7 @@
                                                         - getReceiveTimeMillis(rat, freq)));
                         }
                     } else {
+                        int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
                         for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
                             txTimeMs[lvl] =
                                     (int) (other.getTransmitDurationMillisAtPowerLevel(lvl, rat)
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
new file mode 100644
index 0000000..e0215f55
--- /dev/null
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.inputmethod.stresstest;
+
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.RemoteInput;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.platform.test.annotations.RootPermissionTest;
+import android.provider.Settings;
+import android.view.KeyEvent;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+@RootPermissionTest
+@RunWith(AndroidJUnit4.class)
+public final class NotificationTest {
+
+    private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(10);
+
+    private static final String CHANNEL_ID = "TEST_CHANNEL";
+    private static final String CHANNEL_NAME = "Test channel";
+
+    private static final String REPLY_INPUT_KEY = "REPLY_KEY";
+    private static final String REPLY_INPUT_LABEL = "Test reply label";
+    private static final String ACTION_REPLY = "com.android.inputmethod.stresstest.ACTION_REPLY";
+    private static final String REPLY_ACTION_LABEL = "Test reply";
+    private static final int REPLY_REQUEST_CODE = 1;
+
+    private static final String NOTIFICATION_TITLE = "Test notification";
+    private static final String NOTIFICATION_CONTENT = "Test notification content";
+    private static final int NOTIFICATION_ID = 2000;
+
+    // This is for AOSP System UI for phones. When testing customized System UI, please modify here.
+    private static final BySelector REPLY_SEND_BUTTON_SELECTOR =
+            By.res("com.android.systemui", "remote_input_send");
+
+    private Context mContext;
+    private NotificationManager mNotificationManager;
+    private UiDevice mUiDevice;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mNotificationManager = mContext.getSystemService(NotificationManager.class);
+    }
+
+    @After
+    public void tearDown() {
+        mNotificationManager.cancelAll();
+    }
+
+    @Test
+    public void testDirectReply() {
+        postMessagingNotification();
+        mUiDevice.openNotification();
+        mUiDevice.wait(Until.findObject(By.text(REPLY_ACTION_LABEL)), TIMEOUT).click();
+        // Verify that IME is visible.
+        assertThat(mUiDevice.wait(Until.findObject(By.pkg(getImePackage(mContext))), TIMEOUT))
+                .isNotNull();
+        // Type something, which enables the Send button, then click the Send button.
+        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_A);
+        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_B);
+        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_C);
+        mUiDevice.wait(Until.findObject(REPLY_SEND_BUTTON_SELECTOR.enabled(true)), TIMEOUT).click();
+        // Verify that IME is gone.
+        assertThat(mUiDevice.wait(Until.gone(By.pkg(getImePackage(mContext))), TIMEOUT)).isTrue();
+    }
+
+    private void postMessagingNotification() {
+        // Register the channel. It's safe to register the same channel again and again.
+        NotificationChannel channel =
+                new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, IMPORTANCE_HIGH);
+        mNotificationManager.createNotificationChannel(channel);
+
+        // Post inline reply notification.
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                mContext, REPLY_REQUEST_CODE, new Intent().setAction(ACTION_REPLY),
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+        RemoteInput remoteInput = new RemoteInput.Builder(REPLY_INPUT_KEY)
+                .setLabel(REPLY_INPUT_LABEL)
+                .build();
+        Icon icon = Icon.createWithResource(mContext, android.R.drawable.ic_menu_edit);
+        Notification.Action action =
+                new Notification.Action.Builder(icon, REPLY_ACTION_LABEL, pendingIntent)
+                        .addRemoteInput(remoteInput)
+                        .build();
+        Notification notification = new Notification.Builder(mContext, CHANNEL_ID)
+                .setSmallIcon(android.R.drawable.ic_menu_edit)
+                .setContentTitle(NOTIFICATION_TITLE)
+                .setContentText(NOTIFICATION_CONTENT)
+                .addAction(action)
+                .build();
+        mNotificationManager.notify(NOTIFICATION_ID, notification);
+    }
+
+    private static String getImePackage(Context context) {
+        String imeId = Settings.Secure.getString(
+                context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        ComponentName cn = ComponentName.unflattenFromString(imeId);
+        assertThat(cn).isNotNull();
+        return cn.getPackageName();
+    }
+}